diff --git a/app/build.gradle b/app/build.gradle index b97d1a4..525fd76 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,7 +37,7 @@ android { } compileSdkVersion 28 - buildToolsVersion '30.0.0-rc3' + buildToolsVersion '30.0.0-rc4' android { lintOptions { abortOnError false @@ -119,6 +119,16 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.exifinterface:exifinterface:1.2.0' testImplementation 'junit:junit:4.12' + + + def lifecycle_version = "2.2.0" + + // ViewModel and LiveData + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" + + // SU library implementation 'com.jaredrummler:android-shell:1.0.0' // Xposed diff --git a/app/src/debug/java/com/ljmu/andre/snaptools/STApplication.java b/app/src/debug/java/com/ljmu/andre/snaptools/STApplication.java index f1e272a..da4b0bd 100644 --- a/app/src/debug/java/com/ljmu/andre/snaptools/STApplication.java +++ b/app/src/debug/java/com/ljmu/andre/snaptools/STApplication.java @@ -2,13 +2,16 @@ import android.app.Application; -import com.ljmu.andre.ErrorLogger.ErrorLogger; +import com.jaqxues.akrolyb.logger.FileLogger; import com.ljmu.andre.snaptools.Networking.VolleyHandler; import com.ljmu.andre.snaptools.Utils.ContextHelper; +import com.ljmu.andre.snaptools.Utils.PathProvider; import com.ljmu.andre.snaptools.Utils.TimberUtils; import timber.log.Timber; +import java.io.File; + /** * This class was created by Andre R M (SID: 701439) * It and its contents are free to use by all @@ -29,7 +32,6 @@ public void onCreate() { ContextHelper.set(getApplicationContext()); VolleyHandler.init(getApplicationContext()); - ErrorLogger.init(); Timber.d("Initialising Activities"); super.onCreate(); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4c9c7cc..451b97d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -59,13 +59,6 @@ - - - CBITable getTable(Class cbiObjectClass) { } private static String getDBPath(String name) { - return getPref(DATABASES_PATH) + name + ".db"; + return PathProvider.getDatabasesPath() + name + ".db"; } } diff --git a/app/src/main/java/com/ljmu/andre/ErrorLogger/ErrorLogger.java b/app/src/main/java/com/ljmu/andre/ErrorLogger/ErrorLogger.java deleted file mode 100644 index c44e850..0000000 --- a/app/src/main/java/com/ljmu/andre/ErrorLogger/ErrorLogger.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ljmu.andre.ErrorLogger; - -import android.util.Log; - -import com.ljmu.andre.GsonPreferences.Preferences; -import com.ljmu.andre.snaptools.STApplication; -import com.ljmu.andre.snaptools.Utils.StringUtils; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.util.Date; - -import timber.log.Timber; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class ErrorLogger implements Thread.UncaughtExceptionHandler { - private static ErrorLogger instance; - private UncaughtExceptionHandler defaultHandler; - private Thread thread; - private ErrorProcessor processor; - - private ErrorLogger() { - } - - public void addError(Thread t, int logLevel, Throwable error, String errorMessage) { - checkAndCreateProcessor(); - processor.addError(t, logLevel, error, errorMessage); - } - - private void checkAndCreateProcessor() { - if (thread == null || !thread.isAlive()) { - Timber.d("Creating and starting new Thread"); - thread = new Thread(processor); - thread.start(); - } - } - - public void addError(int logLevel, String error) { - checkAndCreateProcessor(); - processor.addError(logLevel, error); - } - - @Override - public void uncaughtException(Thread t, Throwable e) { - addError(t, Log.ASSERT, e); - defaultHandler.uncaughtException(t, e); - } - - public void addError(Thread t, int logLevel, Throwable error) { - checkAndCreateProcessor(); - processor.addError(t, logLevel, error, null); - } - - public static ErrorLogger getInstance() { - return instance; - } - - public static ErrorLogger init() { - instance = new ErrorLogger(); - - String currentDate = StringUtils.ddMyyyy.format( - new Date(System.currentTimeMillis())); - - instance.processor = new ErrorProcessor(); - instance.processor.init( - Preferences.getExternalPath() + "/" + STApplication.MODULE_TAG + "/ErrorLogs", - String.format("log_%s.log", currentDate) - ); - - instance.defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - Thread.setDefaultUncaughtExceptionHandler(instance); - - return instance; - } -} diff --git a/app/src/main/java/com/ljmu/andre/ErrorLogger/ErrorProcessor.java b/app/src/main/java/com/ljmu/andre/ErrorLogger/ErrorProcessor.java deleted file mode 100644 index 1301114..0000000 --- a/app/src/main/java/com/ljmu/andre/ErrorLogger/ErrorProcessor.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.ljmu.andre.ErrorLogger; - -import android.os.Build.VERSION; -import android.util.Log; - -import com.google.common.io.CharSink; -import com.google.common.io.FileWriteMode; -import com.google.common.io.Files; -import com.ljmu.andre.GsonPreferences.Preferences; -import com.ljmu.andre.snaptools.Framework.FrameworkManager; -import com.ljmu.andre.snaptools.Framework.ModulePack; -import com.ljmu.andre.snaptools.STApplication; -import com.ljmu.andre.snaptools.Utils.Constants; -import com.ljmu.andre.snaptools.Utils.FileUtils; -import com.ljmu.andre.snaptools.Utils.StringUtils; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.ConcurrentModificationException; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import timber.log.Timber; - -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -class ErrorProcessor implements Runnable { - private static final long WRITE_DELAY = TimeUnit.SECONDS.toMillis(30); - private final Object LOCK = new Object(); - private boolean isAlive; - private boolean isInitialised; - private List errorHolders = new ArrayList<>(); - private File outputFile; - private String directory; - private String fileName; - private long lastWriteTime; - - public ErrorProcessor() { - } - - void init(String directory, String fileName) { - this.directory = directory; - this.fileName = fileName; - - isAlive = true; - isInitialised = true; - } - - void addError(Thread thread, int logLevel, Throwable error, String errorMessage) { - Timber.d("Adding error: " + error.getMessage()); - - checkInit(); - - synchronized (LOCK) { - errorHolders.add(new ErrorHolder(logLevel, error, errorMessage)); - LOCK.notifyAll(); - } - } - - private void checkInit() { - if (!isInitialised) - throw new IllegalStateException("ErrorProcessor not Initialised"); - } - - void addError(int logLevel, String error) { - checkInit(); - - synchronized (LOCK) { - errorHolders.add(new ErrorHolder(logLevel, error)); - LOCK.notifyAll(); - } - } - - @Override - public void run() { - checkInit(); - - while (isAlive) { - try { - synchronized (LOCK) { - while (errorHolders.isEmpty()) { - Timber.d("Waiting for entries"); - LOCK.wait(); - Timber.d("Resuming after wait"); - } - } - - long writeTimeDifference = System.currentTimeMillis() - lastWriteTime; - - if (writeTimeDifference < WRITE_DELAY) { - long adjustedWriteDelay = WRITE_DELAY - writeTimeDifference; - Timber.d("Sleeping for %sms", adjustedWriteDelay); - Thread.sleep(adjustedWriteDelay); - Timber.d("Awoken from sleep"); - } - - if (outputFile == null) { - outputFile = FileUtils.createFile(directory, fileName); - - if (outputFile == null) - throw new IllegalStateException("Couldn't create output file: " + fileName); - - sortAndThrowLogs(); - } - - writeCollectedErrors(); - } catch (InterruptedException e) { - Timber.e(e, "Thread Interrupted"); - } - } - } - - private void sortAndThrowLogs() { - File packFolder = new File(directory); - - if (!packFolder.exists()) - return; - - File[] files = packFolder.listFiles(); - - if (files.length > 30) { - Timber.d("Clearing [%s] logs", files.length - 30); - - Arrays.sort( - files, - (f1, f2) -> Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()) - ); - - for (int i = 0; i < 30; i++) { - try { - File file = files[i]; - file.delete(); - } catch (Throwable ignore) { - } - } - } - } - - private void writeCollectedErrors() { - CharSink charSink = Files.asCharSink(outputFile, Charset.defaultCharset(), FileWriteMode.APPEND); - - synchronized (LOCK) { - try { - for (ErrorHolder errorHolder : errorHolders) { - try { - String error = errorHolder.convertToOutput(); - - //SlackUtils.uploadToSlack(botName, System.currentTimeMillis() + "\n" + errorHolder.convertToOutput()); - - error = generateDebugData() + error; - charSink.write(error); - } catch (IOException e) { - Log.e(STApplication.MODULE_TAG, "Error writing error log", e); - } - } - - errorHolders.clear(); - } catch (ConcurrentModificationException e) { - Log.e(STApplication.MODULE_TAG, "Concurrent modification with ErrorLogger", e); - } - } - - lastWriteTime = System.currentTimeMillis(); - } - - private String generateDebugData() { - try { - StringBuilder output = new StringBuilder(); - - if (System.currentTimeMillis() - lastWriteTime >= TimeUnit.MINUTES.toMillis(10)) { - output.append("Framework Version: ").append(Constants.getApkVersionName()).append("\n"); - output.append("OS Version: ").append(VERSION.SDK_INT).append("\n"); - - if (Preferences.getIsInitialised().get()) { - HashSet selectedPacks = getPref(SELECTED_PACKS); - - for (String packName : selectedPacks) { - output.append("Pack: ").append(packName).append("\n"); - - ModulePack pack = FrameworkManager.getModulePack(packName); - if (pack != null) - output.append("\tVersion: ").append(pack.getPackVersion()).append("\n"); - } - } - } - - output.append("[") - .append(StringUtils.HHmmssSSS.format(new Date(System.currentTimeMillis()))) - .append("]"); - - return output.toString(); - } catch (Throwable t) { - Timber.d(t, "Error"); - } - - return ""; - } - - private void stop() { - isAlive = false; - LOCK.notify(); - } - - void addError(int logLevel, Throwable error) { - Timber.d("Error added"); - - checkInit(); - - synchronized (LOCK) { - errorHolders.add(new ErrorHolder(logLevel, error)); - LOCK.notifyAll(); - } - } - - private static class ErrorHolder { - private final int logLevel; - private final Throwable throwable; - private final String errorMessage; - - ErrorHolder(int logLevel, Throwable throwable) { - this(logLevel, throwable, null); - } - - ErrorHolder(int logLevel, Throwable throwable, String errorMessage) { - this.logLevel = logLevel; - this.throwable = throwable; - this.errorMessage = errorMessage; - } - - ErrorHolder(int logLevel, String errorMessage) { - this(logLevel, null, errorMessage); - } - - public int getLogLevel() { - return logLevel; - } - - public Throwable getThrowable() { - return throwable; - } - - public String getErrorMessage() { - return errorMessage; - } - - String convertToOutput() { - if (errorMessage == null && throwable == null) - return null; - - StringBuilder builder = new StringBuilder(); - - switch (logLevel) { - case Log.ASSERT: - builder.append(" [ASSERT] "); - break; - case Log.ERROR: - builder.append(" [ERROR] "); - break; - case Log.WARN: - builder.append(" [WARN] "); - break; - default: - break; - } - - if (errorMessage != null) - builder.append(errorMessage); - - if (throwable != null) { - if (errorMessage != null) - builder.append("\n"); - - builder.append(Log.getStackTraceString(throwable)); - } - - builder.append("\n\n"); - - return builder.toString(); - } - } -} diff --git a/app/src/main/java/com/ljmu/andre/GsonPreferences/DeadlockItemModel.java b/app/src/main/java/com/ljmu/andre/GsonPreferences/DeadlockItemModel.java deleted file mode 100644 index a3e74fe..0000000 --- a/app/src/main/java/com/ljmu/andre/GsonPreferences/DeadlockItemModel.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ljmu.andre.GsonPreferences; - -import androidx.annotation.Nullable; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -class DeadlockItemModel { - private String name; - private StackTraceElement[] traceElements; - - private DeadlockItemModel(String name, StackTraceElement[] traceElements) { - this.name = name; - this.traceElements = traceElements; - } - - static DeadlockItem generate(String name, StackTraceElement[] traceElements, - @Nullable Throwable previousNode) { - return new DeadlockItemModel(name, traceElements).new DeadlockItem(previousNode); - } - - @SuppressWarnings("SerializableInnerClassWithNonSerializableOuterClass") - class DeadlockItem extends Throwable { - private static final long serialVersionUID = -2891934505164278935L; - - private DeadlockItem(Throwable previousNode) { - super(name, previousNode); - } - - /** - * =========================================================================== - * Overridden toString() to remove the original class names from the stack. - * If not overridden each stack trace will be prepended with: - * "com.ljmu.andre.GsonPreference.DeadlockItemModel$DeadlockItem" - * followed by the full classname of the stacktrace item. - *

- * This function will only prepend the stacktrace with "Deadlock Item" - * =========================================================================== - */ - @Override - public String toString() { - String s = "Deadlock Item"; - String message = getLocalizedMessage(); - return (message != null) ? (s + ": " + message) : s; - } - - @Override - public synchronized Throwable fillInStackTrace() { - setStackTrace(traceElements); - return this; - } - } -} diff --git a/app/src/main/java/com/ljmu/andre/GsonPreferences/DeadlockMonitor.java b/app/src/main/java/com/ljmu/andre/GsonPreferences/DeadlockMonitor.java deleted file mode 100644 index 72479a5..0000000 --- a/app/src/main/java/com/ljmu/andre/GsonPreferences/DeadlockMonitor.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.ljmu.andre.GsonPreferences; - -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; - -import com.ljmu.andre.GsonPreferences.DeadlockItemModel.DeadlockItem; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.concurrent.TimeUnit; - -import timber.log.Timber; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -class DeadlockMonitor extends Thread { - private static final int MONITOR_WAIT_TIME = 5; - private static final TimeUnit MONITOR_TIME_UNIT = TimeUnit.SECONDS; - private static DeadlockMonitor instance; - private static int tick = 0; - private static Runnable ticker = () -> { - synchronized (Preferences.LOCK) { - tick = (tick + 1) % Integer.MAX_VALUE; - } - }; - - private DeadlockMonitor(String name) { - super(name); - Timber.d("Created deadlock monitor"); - } - - @Override - public void run() { - HandlerThread lockHandlerThread = new HandlerThread("Pref Lock Handler"); - lockHandlerThread.start(); - Handler lockHandler = new Handler(lockHandlerThread.getLooper()); - - while (!isInterrupted()) { -// Timber.d("Scanning deadlock monitor"); - int lastTick = tick; -// Timber.d("LastTick: " + lastTick); - lockHandler.post(ticker); - - try { - MONITOR_TIME_UNIT.sleep(MONITOR_WAIT_TIME); - } catch (InterruptedException e) { - Timber.e(e); - } - - Timber.d("Tick after monitor: " + tick); - - if (lastTick == tick) { - logAllThreadsStacks(); - } - } - - lockHandler.removeCallbacks(ticker); - lockHandlerThread.quit(); - - Timber.e("DEADLOCK MONITOR EXITED"); - } - - private static void logAllThreadsStacks() { - Thread mainThread = Looper.getMainLooper().getThread(); - - Map stackTraces = new TreeMap<>((left, right) -> { - if (left == right) - return 0; - if (left == mainThread) - return 1; - if (right == mainThread) - return -1; - return right.getName().compareTo(left.getName()); - }); - - stackTraces.putAll(Thread.getAllStackTraces()); - - if (!stackTraces.containsKey(mainThread)) { - stackTraces.put(mainThread, mainThread.getStackTrace()); - } - - DeadlockItem threadReplica = null; - for (Entry entry : stackTraces.entrySet()) { - String threadTitle = getThreadTitle(entry.getKey()); - - threadReplica = DeadlockItemModel.generate(threadTitle, entry.getValue(), threadReplica); - } - - Timber.e(new DeadlockException("Preference Deadlock", threadReplica)); - } - - private static String getThreadTitle(Thread thread) { - return thread.getName() + " (state = " + thread.getState() + ")"; - } - - public synchronized static void init() { - boolean wasDead = false; - - if (instance != null && !instance.isAlive()) { - instance.interrupt(); - wasDead = true; - } - - if (instance == null || wasDead) { - instance = new DeadlockMonitor("Preference Deadlock Monitor"); - instance.start(); - } - } - - private static class DeadlockException extends Exception { - private static final long serialVersionUID = 6021707890871456237L; - - DeadlockException(String message, Throwable cause) { - super(message, cause); - } - } -} diff --git a/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceMap.java b/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceMap.java deleted file mode 100644 index e4a6d61..0000000 --- a/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceMap.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ljmu.andre.GsonPreferences; - -import com.ljmu.andre.GsonPreferences.Preferences.Preference; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * =========================================================================== - * Map capable of being de/serialised without losing the generics - * =========================================================================== - */ -class PreferenceMap extends ConcurrentHashMap { - private static final long serialVersionUID = 2162788535918724249L; - - PreferenceMap() { - } - - PreferenceMap(Map m) { - super(m); - } -} diff --git a/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceObserver.java b/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceObserver.java deleted file mode 100644 index dba1dd6..0000000 --- a/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceObserver.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.ljmu.andre.GsonPreferences; - -import android.os.FileObserver; -import androidx.annotation.Nullable; - -import java.util.concurrent.atomic.AtomicBoolean; - -import timber.log.Timber; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -class PreferenceObserver extends FileObserver { - private static AtomicBoolean isLocalChange = new AtomicBoolean(false); - - PreferenceObserver(String path) { - super(path); - } - - @Override - public void onEvent(int event, @Nullable String path) { - Timber.d("Preference Observer Event: " + event); - - if (isLocalChange.get()) { - Timber.d("Local event occurred... Skipping reload"); - - if (event == FileObserver.CLOSE_NOWRITE || event == FileObserver.CLOSE_WRITE) { - Timber.d("Finished local events"); - isLocalChange.set(false); - } - - return; - } - - switch (event) { - case FileObserver.CLOSE_WRITE: - Timber.d("Preference closed with potential changes"); - Preferences.loadPreferenceMap(); - break; - case FileObserver.CLOSE_NOWRITE: - Timber.d("Preference closed with no changes"); - break; - } - } - - void notifyLocalChange() { - isLocalChange.set(true); - } -} diff --git a/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceUtils.java b/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceUtils.java deleted file mode 100644 index 8297de6..0000000 --- a/app/src/main/java/com/ljmu/andre/GsonPreferences/PreferenceUtils.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.ljmu.andre.GsonPreferences; - -import androidx.annotation.Nullable; - -import com.google.common.io.Closer; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import com.ljmu.andre.GsonPreferences.Preferences.Preference; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import io.reactivex.Observable; -import io.reactivex.annotations.NonNull; -import io.reactivex.observers.DisposableObserver; -import io.reactivex.schedulers.Schedulers; -import timber.log.Timber; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -class PreferenceUtils { - private static final Object WRITE_LOCK = new Object(); - - static void saveMap(File preferenceFile, PreferenceMap preferenceMap, Gson gson) { - Closer closer = Closer.create(); - PreferenceMap copiedPrefs = new PreferenceMap(preferenceMap); - - Observable.fromCallable( - () -> { - Timber.d("Entering write lock"); - synchronized (WRITE_LOCK) { - Timber.d("Entered write lock"); - BufferedWriter writer = closer.register( - new BufferedWriter( - new FileWriter(preferenceFile) - ) - ); - - gson.toJson(copiedPrefs, writer); - writer.flush(); - Timber.d("Exiting write lock"); - } - Timber.d("Exited write lock"); - - return new Object(); - }) - .subscribeOn(Schedulers.io()) - .subscribe(new DisposableObserver() { - @Override - public void onNext(@NonNull Object object) { - } - - @Override - public void onError(@NonNull Throwable e) { - Timber.e(e); - - try { - closer.close(); - } catch (IOException ignored) { - Timber.w("Couldn't close preference file?"); - } - } - - @Override - public void onComplete() { - - try { - closer.close(); - Timber.d("Closing preference file"); - } catch (IOException ignored) { - Timber.w("Couldn't close preference file?"); - } - } - }); - } - - static class PreferenceMapDeserialiser implements JsonDeserializer, JsonSerializer { - private static final Map> classCache = new HashMap<>(16); - private static final Object SERIALIZE_LOCK = new Object(); - Gson gson = new GsonBuilder() - .setLenient() - .create(); - - @Override - public PreferenceMap deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - Timber.d(json.toString()); - PreferenceMap rootMap = new PreferenceMap(); - - JsonArray rootArray; - - try { - rootArray = (JsonArray) json; - } catch (ClassCastException cce) { - Timber.e(new Exception("Malformed Preference Json: " + json)); - return rootMap; - } - - for (Object aRootArray : rootArray) { - try { - JsonObject jsonPreference = (JsonObject) aRootArray; - String name = jsonPreference.get("name").getAsString(); - String strType = jsonPreference.get("type").getAsString(); - Class resolvedClass = getClassFromString(strType); - - if (resolvedClass == null) { - Timber.e(new Exception("Couldn't resolve preference class: " + jsonPreference)); - continue; - } - - Object value = gson.fromJson(jsonPreference.get("value"), resolvedClass); - Preference preference = new Preference(name, value, null, resolvedClass); - - rootMap.put(name, preference); - } catch (Throwable e) { - Timber.e(new Exception("Failed on preference: " + aRootArray.toString(), e)); - } - } - - return rootMap; - } - - @Nullable - private Class getClassFromString(String type) { - Class resolvedClass = classCache.get(type); - - if (resolvedClass != null) - return resolvedClass; - - try { - resolvedClass = Class.forName(type); - classCache.put(type, resolvedClass); - } catch (ClassNotFoundException e) { - Timber.e(e); - } - - return resolvedClass; - } - - @Override - public JsonElement serialize(PreferenceMap src, Type typeOfSrc, JsonSerializationContext context) { - JsonArray rootMap = new JsonArray(); - - synchronized (SERIALIZE_LOCK) { - PreferenceMap copyMap = new PreferenceMap(src); - - for (Entry entry : copyMap.entrySet()) { - try { - Preference preference = entry.getValue(); - - JsonObject jsonPreference = new JsonObject(); - jsonPreference.addProperty("name", entry.getKey()); - Class preferenceType = preference.getType(); - - jsonPreference.addProperty("type", preferenceType.getName()); - - Object prefValue = preference.getValue(); - -// if (prefValue instanceof Map) - jsonPreference.add("value", gson.toJsonTree(prefValue)); -// else -// jsonPreference.add("value", context.serialize(preference.getValue())); - - rootMap.add(jsonPreference); - } catch (Exception e) { - Timber.e(new Exception("Error serialising preference: " + entry, e)); - } - } - } - - return rootMap; - } - } -} diff --git a/app/src/main/java/com/ljmu/andre/GsonPreferences/Preferences.java b/app/src/main/java/com/ljmu/andre/GsonPreferences/Preferences.java deleted file mode 100644 index def6f38..0000000 --- a/app/src/main/java/com/ljmu/andre/GsonPreferences/Preferences.java +++ /dev/null @@ -1,434 +0,0 @@ -package com.ljmu.andre.GsonPreferences; - -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.Environment; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; - -import com.google.common.base.MoreObjects; -import com.google.common.io.Closer; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; -import com.ljmu.andre.ConstantDefiner.Constant; -import com.ljmu.andre.GsonPreferences.PreferenceUtils.PreferenceMapDeserialiser; -import com.ljmu.andre.snaptools.HangErrorActivity; -import com.ljmu.andre.snaptools.Utils.Assert; -import com.ljmu.andre.snaptools.Utils.Constants; -import com.ljmu.andre.snaptools.Utils.FileUtils; -import com.ljmu.andre.snaptools.Utils.MethodTimeout; -import com.ljmu.andre.snaptools.Utils.RequiresFramework; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import timber.log.Timber; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -@SuppressWarnings("unchecked") -public class Preferences { - - static final Object LOCK = new Object(); - private static final String FILE_NAME = "SnapTools_Preferences.json"; - public static PreferenceObserver preferenceObserver; - private static PreferenceMap preferenceMap; - private static File preferenceFile; - private static Gson gson; - private static String cachedExternalDir; - private static AtomicBoolean isInitialised = new AtomicBoolean(false); - - public static AtomicBoolean getIsInitialised() { - return isInitialised; - } - - public static boolean init( - String prefsFilePath) throws IOException { - if (isInitialised.get()) { - Timber.w("Already initialised preferences"); - return true; - } - - if (Constants.getApkFlavor().equals("beta")) { - DeadlockMonitor.init(); - } - - Class type = new TypeToken>() { - }.getClass(); - - Timber.d("Type: " + type); - gson = new GsonBuilder() - .setPrettyPrinting() - .setLenient() - .registerTypeHierarchyAdapter(Map.class, new PreferenceMapDeserialiser()) - .create(); - - synchronized (LOCK) { - preferenceFile = FileUtils.createFile(prefsFilePath, FILE_NAME); - - if (preferenceFile == null) { - Timber.e("Couldn't create Preference File"); - throw new IOException("Couldn't create Preference File"); - } - - Timber.d("Pref: " + preferenceFile.getAbsolutePath()); - - loadPreferenceObserver(); - - loadPreferenceMap(); - Timber.d("Initialised Preferences!"); - } - - isInitialised.set(true); - return true; - } - - public static void loadPreferenceObserver() { - preferenceObserver = new PreferenceObserver(preferenceFile.getAbsolutePath()); - preferenceObserver.startWatching(); - } - - public static void loadPreferenceMap() { - synchronized (LOCK) { - Closer closer = Closer.create(); - - try { - BufferedReader reader = closer.register( - new BufferedReader(new FileReader(preferenceFile)) - ); - - preferenceMap = gson.fromJson(reader, PreferenceMap.class); - - if (preferenceMap == null) - preferenceMap = new PreferenceMap(); - - Timber.d("Loaded Preferences: " + preferenceMap); - } catch (Throwable t) { - Timber.e(t, "Failed to load preferences"); - } finally { - try { - closer.close(); - } catch (IOException ignored) { - } - } - } - } - - @RequiresFramework(78) - public static void forceReset() { - synchronized (LOCK) { - preferenceMap.clear(); - preferenceObserver.notifyLocalChange(); - PreferenceUtils.saveMap(preferenceFile, preferenceMap, gson); - } - } - - public static String getPreferenceFilename() { - return FILE_NAME; - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - @Nullable - public static File getCreateDir(Preference preference) { - File dir = new File((String) getPref(preference)); - dir.mkdirs(); - - if (!dir.exists()) - return null; - - return dir; - } - - public static T getPref(Preference preference) { - initCheck(); - - Object preferenceVal = null; - Preference storedPreference; - - synchronized (LOCK) { - storedPreference = preferenceMap.get(preference.getName()); - } - - if (storedPreference != null) - preferenceVal = storedPreference.getValue(); - - if (preference.getConditionalCheck() != null) - preferenceVal = ConditionalCheck.triggerCheck(preference, preferenceVal); - - if (preferenceVal == null) - return (T) preference.getDefaultVal(); - - return (T) preferenceVal; - } - - private static void initCheck() throws IllegalStateException { - if (!isInitialised.get()) - throw new IllegalStateException("Preference system not Initialised!"); - } - - public static void putPref(Preference preference, Object value) { - initCheck(); - Timber.d("Putting [Pref: %s] [Value: %s]", preference.getName(), String.valueOf(value)); - - synchronized (LOCK) { - preference.setValue(value); - Object oldValue = preferenceMap.put(preference.getName(), preference); - - if (oldValue == null || !oldValue.equals(value)) { - preferenceObserver.notifyLocalChange(); - PreferenceUtils.saveMap(preferenceFile, preferenceMap, gson); - } - } - } - - public static void removePref(Preference preference) { - removePref(preference.getName()); - } - - public static void removePref(String preferenceName) { - initCheck(); - Timber.d("Removing [Pref: %s]", preferenceName); - - synchronized (LOCK) { - Object oldValue = preferenceMap.remove(preferenceName); - - if (oldValue != null) { - preferenceObserver.notifyLocalChange(); - PreferenceUtils.saveMap(preferenceFile, preferenceMap, gson); - } - } - } - - public static String getExternalPath() { - if (cachedExternalDir != null) - return cachedExternalDir; - - cachedExternalDir = useExternalPathFallback(); - - if (cachedExternalDir != null) - return cachedExternalDir; - - try { - cachedExternalDir = new MethodTimeout() { - @Override - public String call() throws Exception { - String externalPath = null; - HashSet externalPathSet = getExternalMounts(); - - if (!externalPathSet.isEmpty()) { - for (String externalMount : externalPathSet) { - if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) { - externalPath = externalMount; - break; - } else { - if (isMounted(externalMount)) { - return externalMount; - } - } - } - } - - if (externalPath == null) - externalPath = useExternalPathFallback(); - - if (externalPath != null) { - if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && - isMounted(externalPath)) - return externalPath; - } - - return null; - } - }.runWithTimeout(5, TimeUnit.SECONDS); - } catch (Exception e) { - Timber.e(e); - } - - if (cachedExternalDir != null) - return cachedExternalDir; - - HangErrorActivity.start("Couldn't find a mounted storage path"); - throw new IllegalStateException("Mounted storage not found"); - } - - @Nullable - private static String useExternalPathFallback() { - - if (VERSION.SDK_INT < VERSION_CODES.P) { - try { - Class environment_cls = Class.forName("android.os.Environment"); - Method setUserRequiredM = environment_cls.getMethod("setUserRequired", boolean.class); - setUserRequiredM.invoke(null, false); - } catch (Exception e) { - Timber.e(e, "Get external path exception"); - } - } - - if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) - return null; - - return Environment.getExternalStorageDirectory().getAbsolutePath(); - } - - @NonNull - private static HashSet getExternalMounts() { - HashSet out = new HashSet<>(); - String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; - String s = ""; - try { - Process process = new ProcessBuilder().command("mount") - .redirectErrorStream(true).start(); - process.waitFor(); - InputStream is = process.getInputStream(); - byte[] buffer = new byte[1024]; - while (is.read(buffer) != -1) { - s = s + new String(buffer); - } - is.close(); - } catch (Exception e) { - Timber.e(e); - } - - // parse output - String[] lines = s.split("\n"); - for (String line : lines) { - if (!line.toLowerCase(Locale.US).contains("asec")) { - if (line.matches(reg)) { - String[] parts = line.split(" "); - for (String part : parts) { - if (part.startsWith("/")) - if (!part.toLowerCase(Locale.US).contains("vold")) - out.add(part); - } - } - } - } - - return out; - } - - @RequiresApi(api = VERSION_CODES.LOLLIPOP) - private static boolean isMounted(String path) { - return Environment.MEDIA_MOUNTED.equals( - Environment.getExternalStorageState(new File(path)) - ); - } - - public static class Preference extends Constant { - @SerializedName("type") - private final Class type; - private final Object defaultVal; - private final ConditionalCheck conditionalCheck; - @SerializedName("value") - private Object value; - - public Preference( - @NonNull String name, - @Nullable Object defaultVal, - @Nullable Class type) { - this(name, null, defaultVal, type, null); - } - - Preference( - @NonNull String name, - @Nullable Object value, - @Nullable Object defaultVal, - @Nullable Class type, - @Nullable ConditionalCheck conditionalCheck) { - super(name); - this.value = value; - this.defaultVal = defaultVal; - this.type = type; - this.conditionalCheck = conditionalCheck; - } - - Preference( - @NonNull String name, - @Nullable Object value, - @Nullable Object defaultVal, - @Nullable Class type) { - this(name, value, defaultVal, type, null); - } - - public Preference( - @NonNull String name, - @Nullable Object defaultVal, - @Nullable Class type, - @Nullable ConditionalCheck conditionalCheck) { - super(name); - this.defaultVal = defaultVal; - this.type = type; - this.conditionalCheck = conditionalCheck; - } - - Object getValue() { - return value; - } - - void setValue(Object value) { - this.value = value; - } - - public T getDefaultVal() { - return (T) defaultVal; - } - - public Class getType() { - return type; - } - - ConditionalCheck getConditionalCheck() { - return conditionalCheck; - } - - @NonNull - @Override - public String getName() { - return Assert.notNull("Null Preference Name", super.getName()); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .omitNullValues() - .add("name", getName()) - .add("type", type) - .add("value", value) - .add("defaultVal", defaultVal) - .toString(); - } - } - - public static abstract class ConditionalCheck { - private static Object triggerCheck(@NonNull Preference preference, @Nullable Object preferenceVal) { - try { - if (preferenceVal != null && - !preferenceVal.equals(preference.getDefaultVal())) - return preferenceVal; - - return preference.getConditionalCheck().performConditionCheck(preference, preferenceVal); - } catch (Exception e) { - Timber.e(e); - return null; - } - } - - @NonNull - protected abstract Object performConditionCheck(Preference preference, Object preferenceVal); - } -} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Databases/CacheDatabase.java b/app/src/main/java/com/ljmu/andre/snaptools/Databases/CacheDatabase.java index d79d529..09357de 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Databases/CacheDatabase.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Databases/CacheDatabase.java @@ -6,11 +6,9 @@ import com.ljmu.andre.CBIDatabase.CBIObject; import com.ljmu.andre.CBIDatabase.CBITable; +import com.ljmu.andre.snaptools.Utils.PathProvider; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.DATABASES_PATH; - /** * This class was created by Andre R M (SID: 701439) * It and its contents are free to use by all @@ -23,7 +21,7 @@ public class CacheDatabase { public static CBIDatabaseCore init(Context context) { if (databaseCore == null) { - String dbPath = getPref(DATABASES_PATH); + String dbPath = PathProvider.getDatabasesPath(); databaseCore = new CBIDatabaseCore( context, dbPath + DB_NAME, VERSION diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/ApkUpdate.java b/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/ApkUpdate.java index dc25f1f..d4e55c2 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/ApkUpdate.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/ApkUpdate.java @@ -12,11 +12,10 @@ import com.ljmu.andre.snaptools.BuildConfig; import com.ljmu.andre.snaptools.Dialogs.ThemedDialog; import com.ljmu.andre.snaptools.Networking.Helpers.CheckAPKUpdate; +import com.ljmu.andre.snaptools.Utils.PathProvider; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.IGNORED_UPDATE_VERSION_CODE; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.TEMP_PATH; import static com.ljmu.andre.snaptools.Utils.FrameworkViewFactory.getSpannedHtml; import static com.ljmu.andre.snaptools.Utils.ResourceUtils.getId; import static com.ljmu.andre.snaptools.Utils.ResourceUtils.getLayout; @@ -67,7 +66,7 @@ public void onCreate(LayoutInflater inflater, View parent, ViewGroup content, Th CheckAPKUpdate.updateApk( activity, update.getUrlToDownload().toString(), - getPref(TEMP_PATH), + PathProvider.getTempPath(), "SnapTools_" + update.getLatestVersion() + ".apk" ); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/PackUpdate.java b/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/PackUpdate.java index 88a5071..9927669 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/PackUpdate.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/Content/PackUpdate.java @@ -15,7 +15,7 @@ import com.ljmu.andre.snaptools.Networking.Packets.PackDataPacket; import com.ljmu.andre.snaptools.Utils.ContextHelper; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.IGNORED_PACK_UPDATE_VERSION; import static com.ljmu.andre.snaptools.Utils.FrameworkViewFactory.getSpannedHtml; import static com.ljmu.andre.snaptools.Utils.ResourceUtils.getId; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/ThemedDialog.java b/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/ThemedDialog.java index ffce704..38c1574 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/ThemedDialog.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Dialogs/ThemedDialog.java @@ -14,7 +14,7 @@ import android.widget.TextView; import android.widget.Toast; -import com.ljmu.andre.GsonPreferences.Preferences.Preference; +import com.jaqxues.akrolyb.prefs.Preference; import com.ljmu.andre.snaptools.Utils.Assert; import com.ljmu.andre.snaptools.Utils.RequiresFramework; import com.ljmu.andre.snaptools.Utils.SafeToast; @@ -23,7 +23,7 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.ContextHelper.getModuleContext; import static com.ljmu.andre.snaptools.Utils.ResourceUtils.getLayout; import static com.ljmu.andre.snaptools.Utils.ResourceUtils.getStyle; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java b/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java index 9c06291..6280219 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java @@ -1,6 +1,7 @@ package com.ljmu.andre.snaptools.EventBus.Events; import com.google.common.base.MoreObjects; +import timber.log.Timber; /** * This class was created by Andre R M (SID: 701439) @@ -46,4 +47,10 @@ public String toString() { public enum EventRequest { UNLOAD, LOAD, DELETE, DOWNLOAD, DOWNLOAD_TUTORIAL, SHOW_ROLLBACK, SHOW_CHANGELOG } + + public interface EventHandler { + void handleEvent(PackEventRequest packEventRequest); + + EventHandler ignoreEvents = packEventRequest -> Timber.d("Ignoring event #%d", packEventRequest.request.ordinal()); + } } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/FAQFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/FAQFragment.java index fd503ed..831ddf4 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/FAQFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/FAQFragment.java @@ -41,8 +41,8 @@ import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_FAQS; import static com.ljmu.andre.snaptools.Utils.FrameworkViewFactory.getSpannedHtml; import static com.ljmu.andre.snaptools.Utils.ResourceUtils.getDSLView; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/HomeFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/HomeFragment.java index d58e5d0..ba6be7c 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/HomeFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/HomeFragment.java @@ -31,8 +31,8 @@ import butterknife.Unbinder; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SHOWN_ANDROID_P_WARNING; /** @@ -68,6 +68,21 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, txtAppVersion.setText(BuildConfig.VERSION_NAME); setTutorialDetails(TUTORIAL_DETAILS); +<<<<<<< HEAD +======= + //resizeThis(); + + if (!getPref(SHOWN_ANDROID_P_WARNING) && VERSION.SDK_INT >= Build.VERSION_CODES.P) { + DialogFactory.createErrorDialog( + getActivity(), + getString(R.string.android_p_warning_title), + getString(R.string.android_p_warning_message) + ).show(); + + putPref(SHOWN_ANDROID_P_WARNING, true); + } + +>>>>>>> f052d4d... Integrate Logger and Preferences from akrolyb return layoutContainer; } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java index b488508..2b8193c 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java @@ -61,7 +61,7 @@ import butterknife.Unbinder; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_PACKS; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS; import static com.ljmu.andre.snaptools.Utils.FrameworkViewFactory.getSpannedHtml; @@ -262,7 +262,7 @@ public void generateTutorialData() { List tutorialDataList = new ArrayList<>(tutorialVersions.size()); for (String tutorialVersion : tutorialVersions) - tutorialDataList.add(ServerPackMetaData.getTutorialPack(tutorialVersion)); + tutorialDataList.add(ServerPackMetaData.getTutorialPack(tutorialVersion, PackEventRequest.EventHandler.ignoreEvents)); setPacks(tutorialDataList); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.kt b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.kt new file mode 100644 index 0000000..aecf983 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.kt @@ -0,0 +1,337 @@ +package com.ljmu.andre.snaptools.Fragments + +import android.os.Bundle +import android.text.format.DateUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter.base.BaseQuickAdapter +import com.jaqxues.akrolyb.prefs.getPref +import com.ljmu.andre.snaptools.Dialogs.Content.PackHistory +import com.ljmu.andre.snaptools.Dialogs.DialogFactory +import com.ljmu.andre.snaptools.Dialogs.ThemedDialog +import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest +import com.ljmu.andre.snaptools.Exceptions.PacketResultException +import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.ServerPackMetaData +import com.ljmu.andre.snaptools.Networking.Helpers.DownloadModulePack +import com.ljmu.andre.snaptools.Networking.Helpers.GetPackChangelog +import com.ljmu.andre.snaptools.Networking.Packets.PackDataPacket +import com.ljmu.andre.snaptools.R +import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter +import com.ljmu.andre.snaptools.Utils.* +import com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_PACKS +import com.ljmu.andre.snaptools.Utils.FrameworkViewFactory.getSpannedHtml +import com.ljmu.andre.snaptools.Utils.StringUtils.htmlHighlight +import com.ljmu.andre.snaptools.viewmodel.PackViewModel +import kotlinx.android.synthetic.main.frag_pack_downloader.* +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 25.05.20 - Time 19:18. + */ +class PackDownloaderFragment : FragmentHelper(), BaseQuickAdapter.OnItemChildClickListener { + @Suppress("UNCHECKED_CAST") + val adapter: ExpandableItemAdapter> + get() { + return recyclerView.adapter as? ExpandableItemAdapter> + ?: throw IllegalStateException("Could not be cast to expected type") + } + val recyclerView: RecyclerView + get() { + check(runningTutorial) { "Only allowing getting PackView for Tutorials" } + return recycler_pack_downloader + } + private lateinit var viewModel: PackViewModel + override fun getMenuId() = null + + override fun getName() = TAG + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.frag_pack_downloader, container, false) + viewModel = ViewModelProvider(requireActivity()).get(PackViewModel::class.java) + return view + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + recycler_pack_downloader.layoutManager = LinearLayoutManager(requireContext()) + + val adapter = ExpandableItemAdapter(emptyList()).apply { + bindToRecyclerView(recycler_pack_downloader) + addType(PackMetaData.type, PackMetaData.layoutRes) + addType(ExpandableItemAdapter.TextItemEntity.type, ExpandableItemAdapter.TextItemEntity.layoutRes) + addType(ServerPackMetaData.ServerPackToolbarItem.type, ServerPackMetaData.ServerPackToolbarItem.layoutRes) + setEmptyView(R.layout.layout_empty_packs) + setOnItemChildClickListener(this@PackDownloaderFragment) + } + + swipe_layout.setOnRefreshListener { + if (runningTutorial) { + swipe_layout.isRefreshing = false + return@setOnRefreshListener + } + viewModel.refreshRemotePacks(PackEventRequest.EventHandler.ignoreEvents, requireActivity(), true) + } + + viewModel.remoteMetadata.observe(this.viewLifecycleOwner, Observer { request -> + if (request is Request.Pending) { + swipe_layout.isRefreshing = true + return@Observer + } + request as Request.Loaded + + swipe_layout.isRefreshing = false + if (runningTutorial) return@Observer + + when (val result = request.result) { + is Result.Success -> { + recycler_pack_downloader?.animateSequentGroup() + val packs = result.data.toMutableList() + packs.sort() + + adapter.setNewData(packs as List>?) + if (activity?.isFinishing == false) updateLastChecked() + } + is Result.Error -> { + val activity = activity ?: return@Observer + val exception = result.exception as PacketResultException + DialogFactory.createErrorDialog( + activity, + exception.title, + exception.message, + exception.errorCode + ).show() + } + } + }) + + viewModel.eventDispatcher.addEventObserver(this) { + handlePackEvent(it) + } + } + + override fun onResume() { + super.onResume() + if (runningTutorial) viewModel.setTutorialPacks() + else viewModel.refreshRemotePacks(PackEventRequest.EventHandler.ignoreEvents, requireActivity(), false) + } + + override fun onPause() { + super.onPause() + viewModel.clearRemotePacks() + } + + override fun progressTutorial() {} + + private fun updateLastChecked() { + val lastChecked = LAST_CHECK_PACKS.getPref() + if (lastChecked == 0L) { + txt_last_checked.visibility = View.GONE + return + } + + val formatted = DateUtils.getRelativeDateTimeString( + activity, + lastChecked, + DateUtils.SECOND_IN_MILLIS, + DateUtils.WEEK_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE + ) as String + + txt_last_checked.text = getSpannedHtml("Last Checked: " + htmlHighlight(formatted)) + txt_last_checked.visibility = View.VISIBLE + } + + private fun handlePackEvent(evt: Any) { + when (evt) { + is PackDeleteEvent -> { + } + is PackDownloadEvent -> { + when (evt.state) { + PackDownloadEvent.DownloadState.SUCCESS -> { + DialogFactory.createBasicMessage( + requireActivity(), + "Success", + "Module Pack successfully downloaded" + ).show() + PackUtils.killSCService(activity) + } + PackDownloadEvent.DownloadState.FAIL -> { + DialogFactory.createErrorDialog( + requireActivity(), + "Download Failed", + "Failed to download Pack File\n\n${evt.message}", + evt.responseCode + ).show() + } + PackDownloadEvent.DownloadState.SKIP -> { + Timber.i("Ignoring skipped download state") + } + null -> { + throw IllegalStateException() + } + } + } + is PackEventRequest -> handlePackEventRequest(evt) + } + } + + private fun handlePackEventRequest(evt: PackEventRequest) { + when (evt.request) { + PackEventRequest.EventRequest.DOWNLOAD -> { + DialogFactory.createConfirmation( + requireActivity(), + "Download Pack", + "Are you sure you wish to download pack \"${evt.packName}\"", + object : ThemedDialog.ThemedClickListener() { + override fun clicked(themedDialog: ThemedDialog) { + val metadata = viewModel.getServerPack(evt.packName) + ?: throw IllegalStateException("Pack not found, but packs loaded") + + viewModel.downloadPack(requireActivity(), metadata) + themedDialog.dismiss() + } + }, + object : ThemedDialog.ThemedClickListener() { + override fun clicked(themedDialog: ThemedDialog) { + themedDialog.dismiss() + } + } + ).show() + } + PackEventRequest.EventRequest.SHOW_ROLLBACK -> { + val metadata = viewModel.getServerPack(evt.packName) + if (metadata == null) { + SafeToast.show( + requireActivity(), + "Failed to get PackMetadata for \"${evt.packName}\"", + Toast.LENGTH_LONG, + true + ) + return + } + ThemedDialog(requireActivity()).apply { + setTitle("Pack History") + setExtension(PackHistory() + .setActivity(requireActivity()) + .setPackType(metadata.type) + .setScVersion(metadata.scVersion) + .setFlavour(metadata.flavour) + .setSelectedPackCallable { + Timber.d("Selected: $it") + + DialogFactory.createConfirmation( + requireActivity(), + "Download old pack?", + "Are you sure you would like to download an old Pack Version? (${it.packVersion})", + object : ThemedDialog.ThemedClickListener() { + override fun clicked(themedDialog: ThemedDialog) { + DownloadModulePack( + requireActivity(), + it.name, it.scVersion, it.packType, it.development, it.packVersion, it.flavour + ).download() + themedDialog.dismiss() + dismiss() + } + } + ) + } + ) + show() + } + } + PackEventRequest.EventRequest.SHOW_CHANGELOG -> { + val metadata = viewModel.getServerPack(evt.packName) + if (metadata == null) { + SafeToast.show( + requireActivity(), + "Failed to retrieve Metadata for specified pack", + Toast.LENGTH_LONG, true + ) + return + } + val livedata = viewModel.requestChangeLog(requireActivity(), metadata) + livedata.observe(viewLifecycleOwner, object: Observer> { + lateinit var progressDialog: ThemedDialog + override fun onChanged(t: Request) { + if (t is Request.Pending) { + progressDialog = DialogFactory.createProgressDialog( + requireActivity(), + "Loading Changelogs", + "Retrieving Changelogs...", + GetPackChangelog.TAG, true + ) + progressDialog.show() + return + } + t as Request.Loaded + progressDialog.dismiss() + + when (t.result) { + is Result.Success -> { + val packet = t.result.data + DialogFactory.createBasicMessage( + requireActivity(), + "Pack Changelog", + """ + Snapchat Version: ${packet.scVersion} + Pack Type: ${packet.packType} + + Release Notes: + ${packet.changelog} + """.trimIndent() + ).show() + } + is Result.Error -> { + val ex = t.result.exception as PacketResultException + DialogFactory.createErrorDialog( + requireActivity(), + ex.title, ex.message, ex.errorCode + ).show() + } + } + livedata.removeObserver(this) + } + }) + } + else -> Timber.d("Ignoring unhandled request") + } + } + + fun generateTutorialData() { +// viewModel.setTutorialPacks() + } + + fun generateMetaData(invalidateCache: Boolean) { +// viewModel.refreshLocalPacks(evtHandler) + } + + companion object { + const val TAG = "Pack Downloader" + } + + override fun onItemChildClick(adapter: BaseQuickAdapter<*, *>, view: View?, position: Int) { + val item = adapter.getItem(position) as? ExpandableItemAdapter.ExpandableItemEntity<*> + + if (item == null) { + Timber.w("Null item clicked") + return + } + + if (item.isExpanded) { + val parent = parentFragment as PackManagerFragment + parent.handleExpandedItem(adapter.getItem(position) as ExpandableItemAdapter.ExpandableItemEntity<*>) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java index b87efd0..2f24a89 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java @@ -251,7 +251,7 @@ public void clicked(ThemedDialog themedDialog) { public static class PackSettingsPagerAdapter extends FragmentPagerAdapter { PackSettingsPagerAdapter(FragmentManager fm) { - super(fm); + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @Override diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java deleted file mode 100644 index c96220d..0000000 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java +++ /dev/null @@ -1,418 +0,0 @@ -package com.ljmu.andre.snaptools.Fragments; - -import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.core.util.Pair; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.Toast; - -import com.google.common.collect.ImmutableList; -import com.google.common.eventbus.Subscribe; -import com.ljmu.andre.snaptools.Dialogs.DialogFactory; -import com.ljmu.andre.snaptools.Dialogs.ThemedDialog; -import com.ljmu.andre.snaptools.Dialogs.ThemedDialog.ThemedClickListener; -import com.ljmu.andre.snaptools.EventBus.EventBus; -import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent; -import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent; -import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent.DownloadState; -import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; -import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest.EventRequest; -import com.ljmu.andre.snaptools.EventBus.Events.PackLoadEvent; -import com.ljmu.andre.snaptools.EventBus.Events.PackUnloadEvent; -import com.ljmu.andre.snaptools.Framework.FrameworkManager; -import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData.FailedPackToolbar; -import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData; -import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData; -import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState; -import com.ljmu.andre.snaptools.R; -import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter; -import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.ExpandableItemEntity; -import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.TextItemEntity; -import com.ljmu.andre.snaptools.Utils.AnimationUtils; -import com.ljmu.andre.snaptools.Utils.PackUtils; -import com.ljmu.andre.snaptools.Utils.PreferenceHelpers; -import com.ljmu.andre.snaptools.Utils.SafeToast; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.Unbinder; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; -import io.reactivex.observers.DisposableObserver; -import io.reactivex.schedulers.Schedulers; -import timber.log.Timber; - -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS; -import static com.ljmu.andre.snaptools.Utils.PreferenceHelpers.collectionContains; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class PackSelectorFragment extends FragmentHelper { - public static final String TAG = "Pack Selector"; - private final List packs = new ArrayList<>(); - - Unbinder unbinder; - @BindView(R.id.swipe_layout) - SwipeRefreshLayout swipeRefreshLayout; - @BindView(R.id.recycler_pack_selector) - RecyclerView list_packs; - private ExpandableItemAdapter adapter; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View layoutContainer = inflater.inflate(R.layout.frag_pack_selector, container, false); - unbinder = ButterKnife.bind(this, layoutContainer); - Timber.d("Create"); - - EventBus.soleRegister(this); - - list_packs.setLayoutManager(new LinearLayoutManager(getContext())); - - adapter = new ExpandableItemAdapter(packs); - adapter.bindToRecyclerView(list_packs); - adapter.addType(PackMetaData.type, PackMetaData.layoutRes); - adapter.addType(TextItemEntity.type, TextItemEntity.layoutRes); - adapter.addType(LocalPackMetaData.LocalPackToolbarItem.type, LocalPackMetaData.LocalPackToolbarItem.layoutRes); - adapter.addType(FailedPackToolbar.type, FailedPackToolbar.layoutRes); - adapter.setEmptyView(R.layout.layout_empty_packs); - - swipeRefreshLayout.setOnRefreshListener( - () -> { - if (runningTutorial) { - swipeRefreshLayout.setRefreshing(false); - return; - } - - generateMetaData(); - } - ); - - return layoutContainer; - } - - @Override - public void onResume() { - super.onResume(); - - if (runningTutorial) - generateTutorialData(); - else - generateMetaData(); - } - - @Override - public void onPause() { - super.onPause(); - packs.clear(); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - unbinder.unbind(); - } - - public void generateMetaData() { - if (runningTutorial) { - generateTutorialData(); - - if (swipeRefreshLayout != null) - swipeRefreshLayout.setRefreshing(false); - return; - } - - PackUtils.getAllMetaData() - .subscribe(new DisposableObserver>() { - @Override - public void onNext(@NonNull Map metaDataMap) { - if (runningTutorial) - return; - - setPacks(metaDataMap.values()); - } - - @Override - public void onError(@NonNull Throwable e) { - if (swipeRefreshLayout != null) - swipeRefreshLayout.setRefreshing(false); - - if (runningTutorial) - return; - - setPacks(Collections.emptyList()); - Timber.e(e); - } - - @Override - public void onComplete() { - if (swipeRefreshLayout != null) - swipeRefreshLayout.setRefreshing(false); - } - }); - } - - public void generateTutorialData() { - List tutorialVersions = new ImmutableList.Builder() - .add("10.0.0.0") - .add("10.1.0.1") - .add("10.12.1.0") - .add("10.16.0.0") - .build(); - - List tutorialDataList = new ArrayList<>(tutorialVersions.size()); - - for (String tutorialVersion : tutorialVersions) - tutorialDataList.add(LocalPackMetaData.getTutorialPack(tutorialVersion)); - - setPacks(tutorialDataList); - } - - public void setPacks(Collection newPacks) { - if (list_packs != null) { - list_packs.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (list_packs == null) - return; - - //At this point the layout is complete and the - //dimensions of recyclerView and any child views are known. - - AnimationUtils.sequentGroup(list_packs); - - list_packs.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - }); - } - - packs.clear(); - packs.addAll(newPacks); - Collections.sort(packs); - - if (adapter != null) { - if (packs.isEmpty()) - adapter.setEmptyView(R.layout.layout_empty_packs); - else - adapter.notifyDataSetChanged(); - } - } - - @Override - public String getName() { - return TAG; - } - - @Override - public Integer getMenuId() { - return null; - } - - @Override - public void onDestroy() { - super.onDestroy(); - EventBus.soleUnregister(this); - } - - @Override - public void progressTutorial() { - } - - @Subscribe - public void handlePackDownloadEvent(PackDownloadEvent downloadEvent) { - Timber.d("Pack Download Event: " + downloadEvent.toString()); - - if (downloadEvent.getState() == DownloadState.SUCCESS) { - if (downloadEvent.getMetaData() == null) - return; - - generateMetaData(); - } - } - - @Nullable - public LocalPackMetaData getMetaDataFromName(String packName) { - Pair result = getMetaDataAndIndexFromName(packName); - - return result == null ? null : result.first; - } - - @Nullable - public Pair getMetaDataAndIndexFromName(String packName) { - int index = -1; - for (Object packObj : packs) { - index++; - if (!(packObj instanceof LocalPackMetaData)) - continue; - - LocalPackMetaData metaData = (LocalPackMetaData) packObj; - - if (metaData.getName().equals(packName)) - return new Pair<>(metaData, index); - } - - return null; - } - - public RecyclerView getRecyclerView() { - return list_packs; - } - - public ExpandableItemAdapter getAdapter() { - return adapter; - } - - @Subscribe - public void handlePackEventRequest(PackEventRequest eventRequest) { - EventRequest request = eventRequest.getRequest(); - Timber.d("New Event Request: " + request.toString()); - - switch (request) { - case UNLOAD: - PreferenceHelpers.removeFromCollection( - SELECTED_PACKS, - eventRequest.getPackName(), - getActivity() - ); - - // If there was no pack to remove, manually update =========================== - if (!FrameworkManager.unloadModPack(eventRequest.getPackName())) - updatePackState(eventRequest.getPackName()); - break; - case LOAD: - FrameworkManager.disableAllPacks(); - - PreferenceHelpers.addToCollection( - SELECTED_PACKS, - eventRequest.getPackName(), - getActivity() - ); - - Observable.fromCallable( - () -> FrameworkManager.loadModPack( - getActivity(), - eventRequest.getPackName(), - new PackLoadState(eventRequest.getPackName()) - )) - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new DisposableObserver() { - @Override - public void onNext(@NonNull PackLoadEvent loadEvent) { - EventBus.getInstance().post(loadEvent); - } - - @Override - public void onError(@NonNull Throwable e) { - Timber.w(e); - FrameworkManager.addFailReason(eventRequest.getPackName(), e.getMessage()); - updatePackState(eventRequest.getPackName()); - } - - @Override - public void onComplete() { - } - }); - - break; - case DELETE: - DialogFactory.createConfirmation( - getActivity(), - "Confirm Action", - "Are you sure you wish to delete this pack?", - new ThemedClickListener() { - @Override - public void clicked(ThemedDialog themedDialog) { - FrameworkManager.deleteModPack(eventRequest.getPackName(), getActivity()); - - if (collectionContains(SELECTED_PACKS, eventRequest.getPackName())) { - String message = "Failed to disable deleted pack: " + eventRequest.getPackName(); - Timber.e(message); - SafeToast.show(getActivity(), message, Toast.LENGTH_LONG); - } - - themedDialog.dismiss(); - } - } - ).show(); - break; - default: - Timber.d("Ignoring Unhandled Request"); - } - } - - public void updatePackState(String packName) { - int packIndex = getIndexFromName(packName); - if (packIndex != -1) { - adapter.notifyItemChanged(packIndex); - ExpandableItemEntity entity = adapter.getItem(packIndex); - - if (entity == null || !entity.isExpanded()) - return; - - while (++packIndex < adapter.getItemCount()) { - entity = adapter.getItem(packIndex); - - Timber.d("Entity: " + entity); - if (!(entity instanceof PackMetaData)) { - adapter.notifyItemChanged(packIndex); - } else - break; - } - } - } - - public int getIndexFromName(String packName) { - int index = -1; - Timber.d("Adapter Count: " + adapter.getItemCount()); - - for (Object packObj : packs) { - index++; - - if (!(packObj instanceof LocalPackMetaData)) - continue; - - LocalPackMetaData metaData = (LocalPackMetaData) packObj; - - if (metaData.getName().equals(packName)) - return index; - } - - return -1; - } - - @Subscribe - public void handlePackLoadEvent(PackLoadEvent loadEvent) { - updatePackState(loadEvent.getModulePack().getPackName()); - } - - @Subscribe - public void handlePackUnloadEvent(PackUnloadEvent unloadEvent) { - updatePackState(unloadEvent.getPackMetaData().getName()); - } - - @Subscribe - public void handlePackDeleteEvent(PackDeleteEvent deleteEvent) { - int index = getIndexFromName(deleteEvent.getPackName()); - adapter.collapse(index); - adapter.remove(index); - - FrameworkManager.deleteModPack(deleteEvent.getPackName(), null); - } -} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.kt b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.kt new file mode 100644 index 0000000..81187cf --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.kt @@ -0,0 +1,208 @@ +package com.ljmu.andre.snaptools.Fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver +import android.widget.Toast +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.ljmu.andre.snaptools.Dialogs.DialogFactory +import com.ljmu.andre.snaptools.Dialogs.ThemedDialog +import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest +import com.ljmu.andre.snaptools.EventBus.Events.PackLoadEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackUnloadEvent +import com.ljmu.andre.snaptools.Framework.FrameworkManager +import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData +import com.ljmu.andre.snaptools.R +import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter +import com.ljmu.andre.snaptools.Utils.AnimationUtils +import com.ljmu.andre.snaptools.Utils.Result +import com.ljmu.andre.snaptools.Utils.SafeToast +import com.ljmu.andre.snaptools.Utils.consumeResult +import com.ljmu.andre.snaptools.viewmodel.PackViewModel +import kotlinx.android.synthetic.main.frag_pack_selector.* +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 14:23. + */ + +class PackSelectorFragment : FragmentHelper() { +// @Suppress("UNCHECKED_CAST") + val adapter: ExpandableItemAdapter> + get() { + return recyclerView.adapter as? ExpandableItemAdapter> + ?: throw IllegalStateException("Could not be cast to expected type") + } + val recyclerView: RecyclerView + get() { + check(runningTutorial) { "Only allowing getting PackView for Tutorials" } + return recycler_pack_selector + } + private val evtHandler = PackEventRequest.EventHandler { handlePackActions(it) } + private lateinit var viewModel: PackViewModel + + override fun getMenuId() = null + + override fun getName() = TAG + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val layoutContainer = inflater.inflate(R.layout.frag_pack_selector, container, false) + viewModel = ViewModelProvider(requireActivity()).get(PackViewModel::class.java) + + return layoutContainer + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + recycler_pack_selector.layoutManager = LinearLayoutManager(requireContext()) + + val adapter = ExpandableItemAdapter(emptyList()).apply { + bindToRecyclerView(recycler_pack_selector) + addType(PackMetaData.type, PackMetaData.layoutRes) + addType(ExpandableItemAdapter.TextItemEntity.type, ExpandableItemAdapter.TextItemEntity.layoutRes) + addType(LocalPackMetaData.type, LocalPackMetaData.layoutRes) + addType(FailedPackMetaData.FailedPackToolbar.type, FailedPackMetaData.layoutRes) + setEmptyView(R.layout.layout_empty_packs) + } + + // Listening to Packs in ViewModel + viewModel.localMetadata.observe(viewLifecycleOwner, Observer { packs -> + + // Animating + recycler_pack_selector.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + val recycler = recycler_pack_selector ?: return + //At this point the layout is complete and the + //dimensions of recyclerView and any child views are known. + AnimationUtils.sequentGroup(recycler) + recycler.viewTreeObserver.removeOnGlobalLayoutListener(this) + } + }) + adapter.setNewData(packs) + swipe_layout.isRefreshing = false + }) + + swipe_layout.setOnRefreshListener { + if (runningTutorial) { + swipe_layout.isRefreshing = false + return@setOnRefreshListener + } + viewModel.refreshLocalPacks(evtHandler) + } + } + + override fun onPause() { + super.onPause() + viewModel.clearPacks() + } + + override fun onResume() { + super.onResume() + + if (runningTutorial) viewModel.setTutorialPacks() + else viewModel.refreshLocalPacks(evtHandler) + } + + private fun handlePackStateEvents(packEvents: Any) { + when(packEvents) { + is PackLoadEvent -> updatePackState(packEvents.packName) + + is PackUnloadEvent -> updatePackState(packEvents.packMetaData.name) + + is PackDeleteEvent -> { + val idx = viewModel.getInfoFromName(packEvents.packName)!!.second + val adapter = recycler_pack_selector.adapter!! as ExpandableItemAdapter<*> + adapter.collapse(idx) + adapter.remove(idx) + } + + is PackEventRequest -> handlePackActions(packEvents) + } + } + + private fun handlePackActions(packRequest: PackEventRequest) { + when(packRequest.request) { + PackEventRequest.EventRequest.UNLOAD -> { + viewModel.unloadPack(packRequest.packName, requireActivity()) + } + PackEventRequest.EventRequest.LOAD -> { + viewModel.enablePack(packRequest.packName, requireActivity()).consumeResult { + if (it is Result.Error) { + FrameworkManager.addFailReason(packRequest.packName, it.exception.message) + updatePackState(packRequest.packName) + } + } + } + PackEventRequest.EventRequest.DELETE -> { + fun deletePack() { + if (viewModel.deletePack(packRequest.packName, requireActivity(), evtHandler) is Result.Error) { + SafeToast.show(activity, "Failed to disable Pack: ${packRequest.packName}", Toast.LENGTH_LONG) + } + } + val pack = viewModel.localMetadata.value?.find { packRequest.packName == it.name } + ?: throw IllegalStateException("Pack to delete was not found") + + // If the Pack has failed to load, delete without confirmation + if (pack is FailedPackMetaData) { + deletePack() + return + } + DialogFactory.createConfirmation( + requireActivity(), + "Confirm Action", + "Are you sure you wish to delete this pack?", + object: ThemedDialog.ThemedClickListener() { + override fun clicked(themedDialog: ThemedDialog) { + deletePack() + themedDialog.dismiss() + } + } + ) + } + else -> Timber.d("Ignoring unhandled request") + } + } + + private fun updatePackState(packName: String) { + var (_, idx) = viewModel.getInfoFromName(packName) ?: return + val adapter = recycler_pack_selector.adapter!! as ExpandableItemAdapter<*> + adapter.notifyItemChanged(idx) + var el = adapter.getItem(idx) + + if (el == null || !el.isExpanded) return + + while (++idx < adapter.itemCount) { + el = adapter.getItem(idx) + + if (el !is PackMetaData) + adapter.notifyItemChanged(idx) + else break + } + } + + override fun progressTutorial() { + } + + fun generateTutorialData() { +// viewModel.setTutorialPacks() + } + + fun generateMetaData() { +// viewModel.refreshLocalPacks(evtHandler) + } + + companion object { + const val TAG = "Pack Selector" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/SettingsFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/SettingsFragment.java index 7019bc9..2ae9ad9 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/SettingsFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/SettingsFragment.java @@ -17,7 +17,7 @@ import android.widget.TextView; import android.widget.Toast; -import com.ljmu.andre.GsonPreferences.Preferences; +import com.jaqxues.akrolyb.prefs.PrefManager; import com.ljmu.andre.Translation.Translator; import com.ljmu.andre.snaptools.BuildConfig; import com.ljmu.andre.snaptools.Dialogs.Content.TextInput; @@ -35,14 +35,8 @@ import com.ljmu.andre.snaptools.Repackaging.RepackageManager; import com.ljmu.andre.snaptools.UIComponents.Adapters.CenteredArrayAdapter; import com.ljmu.andre.snaptools.UIComponents.UITheme; -import com.ljmu.andre.snaptools.Utils.BackupRestoreUtils; +import com.ljmu.andre.snaptools.Utils.*; import com.ljmu.andre.snaptools.Utils.CustomObservers.SimpleObserver; -import com.ljmu.andre.snaptools.Utils.MiscUtils; -import com.ljmu.andre.snaptools.Utils.PackUtils; -import com.ljmu.andre.snaptools.Utils.SafeToast; -import com.ljmu.andre.snaptools.Utils.ShellUtils; -import com.ljmu.andre.snaptools.Utils.StringUtils; -import com.ljmu.andre.snaptools.Utils.ThemeUtils; import java.io.File; import java.util.ArrayList; @@ -56,10 +50,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getCreateDir; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.BACKUP_PATH; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; +import static com.ljmu.andre.snaptools.Utils.FileUtils.getCreateDir; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.BACK_OPENS_MENU; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.CHECK_APK_UPDATES; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.CHECK_PACK_UPDATES; @@ -70,7 +63,6 @@ import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.REPACKAGE_NAME; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SHOW_TRANSITION_ANIMATIONS; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SYSTEM_ENABLED; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.TEMP_PATH; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.TRANSLATION_LOCALE; import static com.ljmu.andre.snaptools.Utils.PreferenceHelpers.putAndKill; import static com.ljmu.andre.snaptools.Utils.StringUtils.htmlHighlight; @@ -242,8 +234,18 @@ public void clicked(ThemedDialog themedDialog) { themedDialog.dismiss(); CheckAPKUpdate.updateApk( getActivity(), +<<<<<<< HEAD +<<<<<<< HEAD "https://github.com/haydhook/SnapTools_DataProvider/blob/master/Apks/Files/SnapTools-" + selection + ".apk?raw=true", getPref(TEMP_PATH), +======= + "https://github.com/jaqxues/SnapTools_DataProvider/blob/master/Apks/Files/SnapTools-" + selection + ".apk?raw=true", + PathProvider.getTempPath(), +>>>>>>> f052d4d... Integrate Logger and Preferences from akrolyb +======= + "https://github.com/jaqxues/SnapTools_DataProvider/blob/master/Apks/Files/SnapTools-" + selection + ".apk?raw=true", + PathProvider.getTempPath(), +>>>>>>> f052d4d... Integrate Logger and Preferences from akrolyb "SnapTools_" + selection + ".apk", selectionResultListener ); @@ -419,7 +421,7 @@ private void initBackupRestore() { List restoreValues = new ArrayList<>(); restoreValues.add("Current"); - File backupDir = getCreateDir(BACKUP_PATH); + File backupDir = getCreateDir(PathProvider.getBackupPath()); /** * =========================================================================== @@ -476,7 +478,7 @@ public void clicked(ThemedDialog themedDialog) { return; } - Preferences.loadPreferenceMap(); + PrefManager.INSTANCE.loadPrefMap(); if (getPref(KILL_SC_ON_CHANGE)) PackUtils.killSCService(getActivity()); @@ -709,7 +711,7 @@ public void onNext(Boolean aBoolean) { return; } - Preferences.forceReset(); + PrefManager.forceReset(); SafeToast.show( getActivity(), "Settings reset, it is recommended to restart SnapTools.", diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/ShopFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/ShopFragment.java index 0d07890..9f155c8 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/ShopFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/ShopFragment.java @@ -50,8 +50,8 @@ import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.HAS_SHOWN_PAY_MODEL_REASONING; /** diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/FrameworkManager.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/FrameworkManager.java index ecf89e3..5dab439 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/FrameworkManager.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/FrameworkManager.java @@ -15,11 +15,7 @@ import com.ljmu.andre.snaptools.Framework.Utils.LoadState.State; import com.ljmu.andre.snaptools.Framework.Utils.ModuleLoadState; import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState; -import com.ljmu.andre.snaptools.Utils.AnimationUtils; -import com.ljmu.andre.snaptools.Utils.ContextHelper; -import com.ljmu.andre.snaptools.Utils.FileUtils; -import com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef; -import com.ljmu.andre.snaptools.Utils.PreferenceHelpers; +import com.ljmu.andre.snaptools.Utils.*; import java.io.File; import java.util.ArrayList; @@ -31,8 +27,7 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.MODULES_PATH; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS; /** @@ -236,7 +231,7 @@ public static PackLoadEvent loadModPack(Context context, String packname, PackLoadState packLoadState) throws ModuleCertificateException, ModulePackFatalError, ModulePackNotFound, ModulePackLoadAborted { // Get an instance of ModulePackImpl from within the .jar file =============== - File modulePackFile = new File((String) getPref(MODULES_PATH), packname + ".jar"); + File modulePackFile = new File(PathProvider.getModulesPath(), packname + ".jar"); ModulePack modulePack = ModulePack.getInstance(context, modulePackFile, packLoadState); synchronized (INSERT_PACK_LOCK) { diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java index 6c9c039..10725c9 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java @@ -20,6 +20,10 @@ public class FailedPackMetaData extends LocalPackMetaData { private String reason; + public FailedPackMetaData(PackEventRequest.EventHandler dispatcher) { + super(dispatcher); + } + @Override public String getDisplayName() { return getName(); @@ -44,7 +48,7 @@ public FailedPackMetaData setReason(String reason) { return this; } - public static class FailedPackToolbar extends ExpandableItemEntity { + public class FailedPackToolbar extends ExpandableItemEntity { public static final int layoutRes = R.layout.failed_pack_toolbar; public static final int type = 3; private FailedPackMetaData linkedMeta; @@ -69,14 +73,15 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { ImageButton disableBtn = (ImageButton) holder.itemView.findViewById(R.id.btn_delete); disableBtn.setOnClickListener( v -> { - EventBus.getInstance().post( + eventDispatcher.handleEvent( new PackEventRequest( EventRequest.UNLOAD, linkedMeta.getName() )); - EventBus.getInstance().post( - new PackDeleteEvent( + eventDispatcher.handleEvent( + new PackEventRequest( + EventRequest.DELETE, linkedMeta.getName() )); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java index 246aea6..2956f32 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java @@ -17,6 +17,7 @@ import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter; import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.ExpandableItemEntity; import com.ljmu.andre.snaptools.Utils.PreferenceHelpers; +import kotlin.jvm.functions.Function1; import static android.view.View.GONE; import static com.ljmu.andre.snaptools.Utils.ContextHelper.getModuleResources; @@ -27,6 +28,11 @@ * It and its contents are free to use by all */ public class LocalPackMetaData extends PackMetaData { + + public LocalPackMetaData(PackEventRequest.EventHandler dispatcher) { + super(dispatcher); + } + @Override public void updateHeaderStateHolder(TextView stateHolder) { if (isActive()) { @@ -83,7 +89,7 @@ public int getLevel() { } public static LocalPackMetaData getTutorialPack(String scVersion) { - return (LocalPackMetaData) new LocalPackMetaData() + return (LocalPackMetaData) new LocalPackMetaData(null) .setScVersion(scVersion) .setPackVersion("1.0.0.0") .setLatest(true) @@ -95,8 +101,8 @@ public static LocalPackMetaData getTutorialPack(String scVersion) { .completedBinding(); } - public static LocalPackMetaData from(PackMetaData metaData) { - LocalPackMetaData localMetaData = new LocalPackMetaData(); + public LocalPackMetaData from(PackMetaData metaData, PackEventRequest.EventHandler dispatcher) { + LocalPackMetaData localMetaData = new LocalPackMetaData(dispatcher); localMetaData.setName(metaData.getName()); localMetaData.setDevelopment(metaData.isDeveloper()); localMetaData.setPackVersion(metaData.getPackVersion()); @@ -107,7 +113,7 @@ public static LocalPackMetaData from(PackMetaData metaData) { return localMetaData; } - public static class LocalPackToolbarItem extends ExpandableItemEntity { + public class LocalPackToolbarItem extends ExpandableItemEntity { public static final int layoutRes = R.layout.pack_toolbar_local; public static final int type = 2; public final int level; @@ -147,7 +153,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { )); delete.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.handleEvent( new PackEventRequest( EventRequest.DELETE, linkedMeta.getName() @@ -162,7 +168,8 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { )); toggle.setOnCheckedChangeListener( - (buttonView, isChecked) -> EventBus.getInstance().post( + + (buttonView, isChecked) -> eventDispatcher.handleEvent( new PackEventRequest( isChecked ? EventRequest.LOAD : EventRequest.UNLOAD, linkedMeta.getName() diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java index 9dfac1a..d860712 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java @@ -3,13 +3,13 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; - import com.chad.library.adapter.base.BaseViewHolder; import com.chad.library.adapter.base.entity.MultiItemEntity; import com.g00fy2.versioncompare.Version; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.gson.annotations.SerializedName; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Framework.FrameworkManager; import com.ljmu.andre.snaptools.Framework.ModulePack; import com.ljmu.andre.snaptools.R; @@ -20,7 +20,6 @@ import com.ljmu.andre.snaptools.Utils.AnimationUtils; import com.ljmu.andre.snaptools.Utils.Assert; import com.ljmu.andre.snaptools.Utils.RequiresFramework; - import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -38,6 +37,11 @@ public abstract class PackMetaData extends ExpandableItemEntity implements StatefulListable, Comparable { public static final int layoutRes = R.layout.item_listable_head_stateful; public static final int type = 0; + protected final PackEventRequest.EventHandler eventDispatcher; + + public PackMetaData(PackEventRequest.EventHandler dispatcher) { + eventDispatcher = dispatcher; + } /** * =========================================================================== diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java index e33637d..269f1f1 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java @@ -4,6 +4,7 @@ import android.widget.TextView; import com.chad.library.adapter.base.BaseViewHolder; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.R; import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter; @@ -25,6 +26,7 @@ public abstract class PackUpdateMetaData extends PackMetaData { private boolean hasUpdate; public PackUpdateMetaData(String name) { + super(PackEventRequest.EventHandler.ignoreEvents); setName(name); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java index 044adfe..228f26c 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java @@ -7,6 +7,7 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.core.view.KeyEventDispatcher; import com.chad.library.adapter.base.BaseViewHolder; import com.google.gson.annotations.SerializedName; import com.ljmu.andre.snaptools.BuildConfig; @@ -21,6 +22,7 @@ import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.TextItemEntity; import com.ljmu.andre.snaptools.Utils.RequiresFramework; +import kotlin.jvm.functions.Function1; import timber.log.Timber; import static com.ljmu.andre.snaptools.Utils.ContextHelper.getModuleResources; @@ -45,8 +47,12 @@ public class ServerPackMetaData extends PackMetaData { @SerializedName("is_purchased") private Boolean isPurchased; - public static ServerPackMetaData getTutorialPack(String scVersion) { - return (ServerPackMetaData) new ServerPackMetaData() + public ServerPackMetaData(PackEventRequest.EventHandler dispatcher) { + super(dispatcher); + } + + public static ServerPackMetaData getTutorialPack(String scVersion, PackEventRequest.EventHandler dispatcher) { + return (ServerPackMetaData) new ServerPackMetaData(dispatcher) .setPurchased(false) .setDescription(htmlHighlight("Tutorial Item")) .setHasUpdate(false) @@ -203,7 +209,7 @@ public ServerPackMetaData setPurchased(@Nullable Boolean isPurchased) { return this; } - public static class ServerPackToolbarItem extends ExpandableItemEntity { + public class ServerPackToolbarItem extends ExpandableItemEntity { public static final int layoutRes = R.layout.pack_toolbar_server; public static final int type = 2; public final int level; @@ -236,7 +242,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { download.setImageTintList(ContextCompat.getColorStateList(holder.itemView.getContext(), R.color.textPrimary)); download.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.handleEvent( new PackEventRequest( eventType, linkedMeta.getName() @@ -249,7 +255,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { if (!linkedMeta.isTutorial()) { rollback.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.handleEvent( new PackEventRequest( EventRequest.SHOW_ROLLBACK, linkedMeta.getName() @@ -258,7 +264,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { ); changelog.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.handleEvent( new PackEventRequest( EventRequest.SHOW_CHANGELOG, linkedMeta.getName() diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java index 9de66e1..7f1cb75 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Exceptions.ModuleCertificateException; import com.ljmu.andre.snaptools.Exceptions.ModulePackFatalError; import com.ljmu.andre.snaptools.Exceptions.ModulePackLoadAborted; @@ -242,7 +243,7 @@ public static ModulePack getInstance( throw new ModulePackFatalError("Module pack doesn't contain meta-data"); // Load the metadata embedded into the manifest ============================== - LocalPackMetaData packMetaData = (LocalPackMetaData) new LocalPackMetaData() + LocalPackMetaData packMetaData = (LocalPackMetaData) new LocalPackMetaData(PackEventRequest.EventHandler.ignoreEvents) .setName(modulePackFile.getName().replace(".jar", "")) .setType(mainAttributes.getValue("Type")) .setPackVersion(mainAttributes.getValue("PackVersion")) diff --git a/app/src/main/java/com/ljmu/andre/snaptools/HangErrorActivity.java b/app/src/main/java/com/ljmu/andre/snaptools/HangErrorActivity.java deleted file mode 100644 index 941dd42..0000000 --- a/app/src/main/java/com/ljmu/andre/snaptools/HangErrorActivity.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.ljmu.andre.snaptools; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; - -import com.ljmu.andre.GsonPreferences.Preferences; -import com.ljmu.andre.snaptools.Dialogs.DialogFactory; -import com.ljmu.andre.snaptools.Dialogs.ThemedDialog; -import com.ljmu.andre.snaptools.Dialogs.ThemedDialog.ThemedClickListener; -import com.ljmu.andre.snaptools.Utils.ContextHelper; -import com.ljmu.andre.snaptools.Utils.PackUtils; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.Unbinder; -import timber.log.Timber; - -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.WATCHDOG_HANG_TIMEOUT; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class HangErrorActivity extends AppCompatActivity { - public static final String EXTRA_REASON = "hang_reason"; - @BindView(R.id.txt_message) - TextView txtMessage; - @BindView(R.id.seek_timeout) - SeekBar seekTimeout; - @BindView(R.id.label_timeout) - TextView labelTimeout; - private Unbinder unbinder; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_hang_error); - unbinder = ButterKnife.bind(this); - - - try { - Preferences.init( - Preferences.getExternalPath() + "/" + STApplication.MODULE_TAG + "/" - ); - } catch (Exception e) { - Timber.e(e); - - DialogFactory.createErrorDialog( - this, - "Error Initialising Preferences", - "Preference system not loaded. The reason is likely to be permission issues. The application will terminate to preserve data integrity" - + "\n\n" - + "Reason: " + e.getMessage(), - new ThemedClickListener() { - @Override - public void clicked(ThemedDialog themedDialog) { - themedDialog.dismiss(); - finish(); - } - } - ).setDismissable(false).show(); - } - - initHangTimer(); - - Intent intent = getIntent(); - if (intent == null) - return; - - Bundle extras = intent.getExtras(); - if (extras == null) - return; - - String hangReason = extras.getString(EXTRA_REASON); - if (hangReason == null || hangReason.isEmpty()) - return; - - txtMessage.setText(hangReason); - } - - private void initHangTimer() { - int timeoutMin = 5; - - int prefTimeout = getPref(WATCHDOG_HANG_TIMEOUT); - int displayTimeout = prefTimeout / 1000; - - labelTimeout.setText(displayTimeout + " Seconds"); - - seekTimeout.setMax(30 - timeoutMin); - seekTimeout.setProgress(displayTimeout - timeoutMin); - seekTimeout.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - progress += timeoutMin; - labelTimeout.setText(progress + " Seconds"); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - int progress = seekBar.getProgress(); - progress += timeoutMin; - putPref(WATCHDOG_HANG_TIMEOUT, progress * 1000); - } - }); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - unbinder.unbind(); - } - - @OnClick(R.id.hang_force_kill) - public void onViewClicked() { - PackUtils.killSCService(this); - } - - public static void start(String reason) { - start(ContextHelper.getModuleContext(null), reason); - } - - public static boolean start(Context context, String reason) { - if (context == null) - context = ContextHelper.getModuleContext(null); - - if (context == null) { - Timber.e(new Exception("Couldn't get a valid context to load Hang Activity with")); - return false; - } - - Intent intent = new Intent(); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - intent.setComponent(ComponentName.unflattenFromString("com.ljmu.andre.snaptools/.HangErrorActivity")); - intent.putExtra(HangErrorActivity.EXTRA_REASON, reason); - context.startActivity(intent); - return true; - } - - -} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/HookManager.java b/app/src/main/java/com/ljmu/andre/snaptools/HookManager.java index 86fd846..50c2d81 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/HookManager.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/HookManager.java @@ -9,8 +9,7 @@ import android.os.Process; import android.view.ContextThemeWrapper; -import com.ljmu.andre.ErrorLogger.ErrorLogger; -import com.ljmu.andre.GsonPreferences.Preferences; +import com.jaqxues.akrolyb.logger.FileLogger; import com.ljmu.andre.snaptools.Databases.CacheDatabase; import com.ljmu.andre.snaptools.Dialogs.Content.FrameworkLoadError; import com.ljmu.andre.snaptools.Dialogs.DialogFactory; @@ -18,13 +17,12 @@ import com.ljmu.andre.snaptools.Dialogs.ThemedDialog.ThemedClickListener; import com.ljmu.andre.snaptools.Framework.FrameworkManager; import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState; +import com.ljmu.andre.snaptools.Utils.Common; import com.ljmu.andre.snaptools.Networking.VolleyHandler; -import com.ljmu.andre.snaptools.Utils.ContextHelper; -import com.ljmu.andre.snaptools.Utils.ModuleChecker; -import com.ljmu.andre.snaptools.Utils.TimberUtils; -import com.ljmu.andre.snaptools.Utils.UnhookManager; +import com.ljmu.andre.snaptools.Utils.*; import com.ljmu.andre.snaptools.Utils.XposedUtils.ST_MethodHook; +import java.io.File; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -33,9 +31,8 @@ import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; import timber.log.Timber; - -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.ACCEPTED_TOS; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.CHECK_PACK_UPDATES_SC; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.NOTIFY_ON_LOAD; @@ -111,14 +108,11 @@ public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { Timber.d("PID: %s", Process.myPid()); - ErrorLogger.init(); - Timber.d("Loading preferences"); - Preferences.init( - Preferences.getExternalPath() + "/" + STApplication.MODULE_TAG + "/" - ); + Common.initPrefs(); + Common.plantFileLogger(); - if (!(boolean) getPref(SYSTEM_ENABLED)) { + if (!getPref(SYSTEM_ENABLED)) { Timber.w("System Disabled... Aborting initialisation"); return; } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/MainActivity.java b/app/src/main/java/com/ljmu/andre/snaptools/MainActivity.java index fa2a780..d5c802c 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/MainActivity.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/MainActivity.java @@ -30,7 +30,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.eventbus.Subscribe; -import com.ljmu.andre.GsonPreferences.Preferences; import com.ljmu.andre.Translation.Translator; import com.ljmu.andre.snaptools.Databases.CacheDatabase; import com.ljmu.andre.snaptools.Dialogs.Content.FrameworkLoadError; @@ -55,21 +54,14 @@ import com.ljmu.andre.snaptools.Framework.Module; import com.ljmu.andre.snaptools.Framework.ModulePack; import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState; +import com.ljmu.andre.snaptools.Utils.Common; import com.ljmu.andre.snaptools.Networking.Helpers.CheckAPKUpdate; import com.ljmu.andre.snaptools.Repackaging.RepackageManager; import com.ljmu.andre.snaptools.UIComponents.CustomNavigation; import com.ljmu.andre.snaptools.UIComponents.CustomNavigation.NavigationFragmentListener; import com.ljmu.andre.snaptools.UIComponents.UITheme; -import com.ljmu.andre.snaptools.Utils.Constants; -import com.ljmu.andre.snaptools.Utils.ContextHelper; +import com.ljmu.andre.snaptools.Utils.*; import com.ljmu.andre.snaptools.Utils.CustomObservers.ErrorObserver; -import com.ljmu.andre.snaptools.Utils.MiscUtils; -import com.ljmu.andre.snaptools.Utils.ModuleChecker; -import com.ljmu.andre.snaptools.Utils.RemoteConfig; -import com.ljmu.andre.snaptools.Utils.SafeToast; -import com.ljmu.andre.snaptools.Utils.ShowcaseFactory; -import com.ljmu.andre.snaptools.Utils.ThemeUtils; -import com.ljmu.andre.snaptools.Utils.TranslationDef; import java.util.List; import java.util.Locale; @@ -89,9 +81,8 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; -import static com.ljmu.andre.GsonPreferences.Preferences.getExternalPath; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.Translation.Translator.translate; import static com.ljmu.andre.snaptools.Utils.Constants.APK_CHECK_COOLDOWN; import static com.ljmu.andre.snaptools.Utils.Constants.REMIND_TUTORIAL_COOLDOWN; @@ -269,9 +260,7 @@ private void initialiseApplication() { * =========================================================================== */ try { - Preferences.init( - getExternalPath() + "/" + STApplication.MODULE_TAG + "/" - ); + Common.initPrefs(); } catch (Exception e) { Timber.e(e); diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckAPKUpdate.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckAPKUpdate.java index 202d263..4a9be8f 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckAPKUpdate.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckAPKUpdate.java @@ -19,8 +19,8 @@ import io.reactivex.annotations.Nullable; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.IGNORED_UPDATE_VERSION_CODE; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_APK_UPDATE_CHECK; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LATEST_APK_VERSION_CODE; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckPackUpdate.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckPackUpdate.java index de80db7..143003f 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckPackUpdate.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/CheckPackUpdate.java @@ -18,7 +18,7 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; import static com.ljmu.andre.Translation.Translator.translate; import static com.ljmu.andre.snaptools.Networking.WebRequest.RequestType.STRING; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.IGNORED_PACK_UPDATE_VERSION; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java index 09bb41e..9b13401 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java @@ -9,18 +9,17 @@ import com.ljmu.andre.snaptools.EventBus.EventBus; import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent; import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent.DownloadState; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Exceptions.NullObjectException; import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData; import com.ljmu.andre.snaptools.Networking.Helpers.DownloadFile.DownloadListener; import com.ljmu.andre.snaptools.Utils.Assert; import com.ljmu.andre.snaptools.Utils.ContextHelper; import com.ljmu.andre.snaptools.Utils.PackUtils; +import com.ljmu.andre.snaptools.Utils.PathProvider; import java.io.File; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.MODULES_PATH; - /** * This class was created by Andre R M (SID: 701439) * It and its contents are free to use by all @@ -76,7 +75,7 @@ public void download() { .setMethod(Request.Method.GET) .setContext(activity) .setVolleyTag(VOLLEY_TAG) - .setDirectory(getPref(MODULES_PATH)) + .setDirectory(PathProvider.getModulesPath()) .setFilename(packName + ".jar") // =========================================================================== .addDownloadListener(this) @@ -98,7 +97,7 @@ public void downloadFinished(boolean state, String message, @Nullable File outpu if (outputFile != null) { try { - metaData = PackUtils.getPackMetaData(outputFile); + metaData = PackUtils.getPackMetaData(outputFile, PackEventRequest.EventHandler.ignoreEvents); } catch (NullObjectException e) { state = false; message = e.getMessage(); diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFAQs.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFAQs.java index 6a35ce9..b1738a0 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFAQs.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFAQs.java @@ -1,7 +1,7 @@ package com.ljmu.andre.snaptools.Networking.Helpers; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.Constants.FAQ_CHECK_COOLDOWN; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_FAQS; import static com.ljmu.andre.snaptools.Utils.MiscUtils.calcTimeDiff; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFeatures.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFeatures.java index 9a02dfa..6f39ac3 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFeatures.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetFeatures.java @@ -1,7 +1,7 @@ package com.ljmu.andre.snaptools.Networking.Helpers; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.Constants.FEATURES_CHECK_COOLDOWN; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_FEATURES; import static com.ljmu.andre.snaptools.Utils.MiscUtils.calcTimeDiff; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetRemoteConfig.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetRemoteConfig.java index c1a3817..8318618 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetRemoteConfig.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetRemoteConfig.java @@ -1,7 +1,7 @@ package com.ljmu.andre.snaptools.Networking.Helpers; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.Constants.REMOTE_CONFIG_COOLDOWN; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_REMOTE_CONFIG; import static com.ljmu.andre.snaptools.Utils.MiscUtils.calcTimeDiff; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java index d22990e..ca54c59 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java @@ -5,6 +5,7 @@ import com.android.volley.Request.Method; import com.ljmu.andre.snaptools.Databases.CacheDatabase; import com.ljmu.andre.snaptools.Databases.Tables.ServerPackObject; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData; import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData; import com.ljmu.andre.snaptools.Framework.MetaData.ServerPackMetaData; @@ -31,7 +32,7 @@ import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.Constants.PACK_CHECK_COOLDOWN; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_PACKS; @@ -205,7 +206,7 @@ private static List processPacks(Collection extends SettingBasedLayout { - private Preference preference; + private Preference preference; - public PreferenceBasedLayout(Activity activity, Preference preference) { + public PreferenceBasedLayout(Activity activity, Preference preference) { super(activity, null); this.preference = preference; } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/AnimationUtils.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/AnimationUtils.java index 38f1e77..6560472 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/AnimationUtils.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/AnimationUtils.java @@ -18,7 +18,7 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SHOW_TRANSITION_ANIMATIONS; /** @@ -40,7 +40,7 @@ public static void sequentGroup(Context context, ViewGroup viewGroup) { } public static void sequentGroup(Context context, ViewGroup viewGroup, int duration, int offset, int delay) { - if (!(boolean) getPref(SHOW_TRANSITION_ANIMATIONS)) + if (!getPref(SHOW_TRANSITION_ANIMATIONS)) return; Sequent.origin(viewGroup) diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/BackupRestoreUtils.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/BackupRestoreUtils.java index d633d21..f180e66 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/BackupRestoreUtils.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/BackupRestoreUtils.java @@ -1,7 +1,6 @@ package com.ljmu.andre.snaptools.Utils; import com.google.common.io.Files; -import com.ljmu.andre.GsonPreferences.Preferences; import java.io.File; import java.io.IOException; @@ -9,10 +8,7 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getCreateDir; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.BACKUP_PATH; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.CONTENT_PATH; +import static com.ljmu.andre.snaptools.Utils.FileUtils.getCreateDir; import static com.ljmu.andre.snaptools.Utils.StringUtils.yyyyMMddHHmmss; /** @@ -30,7 +26,7 @@ public static String createFilename(String profileName) { } public static boolean backupCurrentProfile(String profileName) { - File currentPrefFile = new File((String) getPref(CONTENT_PATH), Preferences.getPreferenceFilename()); + File currentPrefFile = new File(PathProvider.getContentPath(), Common.PREF_FILE); if (!currentPrefFile.exists()) { Timber.w("Preference file doesn't exist?"); return false; @@ -55,7 +51,7 @@ public static boolean backupCurrentProfile(String profileName) { } private static File getBackupFile(String profileName) { - File backupDir = getCreateDir(BACKUP_PATH); + File backupDir = getCreateDir(PathProvider.getBackupPath()); if (backupDir == null || !backupDir.exists()) { Timber.w("Backup dir not created"); return null; @@ -73,7 +69,7 @@ public static boolean restoreProfile(String profileName) { } - File currentPrefFile = new File((String) getPref(CONTENT_PATH), Preferences.getPreferenceFilename()); + File currentPrefFile = new File(PathProvider.getContentPath(), Common.PREF_FILE); try { if (!currentPrefFile.exists()) { diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Common.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Common.java new file mode 100644 index 0000000..cd530ff --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Common.java @@ -0,0 +1,39 @@ +package com.ljmu.andre.snaptools.Utils; + +import com.jaqxues.akrolyb.logger.FileLogger; +import com.jaqxues.akrolyb.prefs.PrefManager; +import com.jaqxues.akrolyb.prefs.gson.GsonPrefMapSerializer; +import kotlin.jvm.JvmClassMappingKt; +import kotlin.reflect.KClass; +import timber.log.Timber; + +import java.io.File; + +import static com.ljmu.andre.snaptools.Utils.FileUtils.getCreateDir; + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 25.05.20 - Time 16:25. + */ +public class Common { + public static final String PREF_FILE = "SnapTools_Preferences.json"; + + public static void initPrefs() { + PrefManager.INSTANCE.init( + new File(PathProvider.getContentPath(), PREF_FILE), + new KClass[]{JvmClassMappingKt.getKotlinClass(FrameworkPreferencesDef.class)}, + new GsonPrefMapSerializer() + ); + } + + public static FileLogger plantFileLogger() { + try { + FileLogger fileLogger = FileLogger.Companion.getInstance(getCreateDir(PathProvider.getLogsPath()), true, true); + Timber.plant(fileLogger); + return fileLogger; + } catch (Exception e) { + Timber.e(e, "Failed to initialize Error Logger"); + } + return null; + } +} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/DeviceIdManager.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/DeviceIdManager.java index f01858b..6e9cf30 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/DeviceIdManager.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/DeviceIdManager.java @@ -7,7 +7,7 @@ import com.google.common.hash.Hasher; import com.google.common.hash.Hashing; -import com.ljmu.andre.GsonPreferences.Preferences; +import com.jaqxues.akrolyb.prefs.PrefManager; import com.ljmu.andre.snaptools.Dialogs.DialogFactory; import com.ljmu.andre.snaptools.Dialogs.ThemedDialog; import com.ljmu.andre.snaptools.Dialogs.ThemedDialog.ThemedClickListener; @@ -15,11 +15,13 @@ import java.lang.reflect.Method; import java.nio.charset.Charset; +import java.util.UUID; import io.reactivex.android.schedulers.AndroidSchedulers; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.Translation.Translator.translate; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.INSTALLATION_ID; import static com.ljmu.andre.snaptools.Utils.StringUtils.htmlHighlight; @@ -296,12 +298,13 @@ public synchronized static String getDeviceId(Context context) { * Uses MurMurHash to attempt to further secure the ID * =========================================================================== */ + @SuppressWarnings("UnstableApiUsage") private static String getDeviceIdOldMethod(Context context) { // Hash the ID to make it harder to spoof/guess ============================== Hasher hasher = Hashing.murmur3_128(8435809).newHasher(); - if (Preferences.getIsInitialised().get()) - hasher.putString(getPref(INSTALLATION_ID), Charset.defaultCharset()); + if (PrefManager.isInitialized()) + hasher.putString(getInstallationId(), Charset.defaultCharset()); hasher.putString( getAndroidId(context), @@ -310,4 +313,13 @@ private static String getDeviceIdOldMethod(Context context) { return cachedDeviceId = hasher.hash().toString(); } + + public static String getInstallationId() { + String id = getPref(INSTALLATION_ID); + if (id == null || id.isEmpty()) { + id = UUID.randomUUID().toString(); + putPref(INSTALLATION_ID, id); + } + return id; + } } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/FileUtils.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/FileUtils.java index 6eb45fe..b0a2c88 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/FileUtils.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/FileUtils.java @@ -34,9 +34,6 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.MODULES_PATH; - /** * This class was created by Andre R M (SID: 701439) * It and its contents are free to use by all @@ -255,7 +252,7 @@ public static File getCodeCacheDir(Context context) { } public static void deletePack(@Nullable Activity activity, String name) { - File packFile = new File((String) getPref(MODULES_PATH), name + ".jar"); + File packFile = new File(PathProvider.getModulesPath(), name + ".jar"); if (packFile.exists()) Timber.d("Deleted ModulePack JAR: " + packFile.delete()); @@ -418,6 +415,18 @@ public static boolean tryCreate(File newFile) { return false; } + @SuppressWarnings("ResultOfMethodCallIgnored") + @Nullable + public static File getCreateDir(String path) { + File dir = new File(path); + dir.mkdirs(); + + if (!dir.exists()) + return null; + + return dir; + } + public static boolean streamCopy(ByteArrayOutputStream byteOutput, OutputStream targetStream) { Timber.d("Copying stream"); diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/FrameworkPreferencesDef.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/FrameworkPreferencesDef.java deleted file mode 100644 index d09f1d8..0000000 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/FrameworkPreferencesDef.java +++ /dev/null @@ -1,347 +0,0 @@ -package com.ljmu.andre.snaptools.Utils; - -import androidx.annotation.NonNull; - -import com.ljmu.andre.ConstantDefiner.ConstantDefiner; -import com.ljmu.andre.GsonPreferences.Preferences.ConditionalCheck; -import com.ljmu.andre.GsonPreferences.Preferences.Preference; -import com.ljmu.andre.snaptools.BuildConfig; -import com.ljmu.andre.snaptools.STApplication; -import com.ljmu.andre.snaptools.UIComponents.UITheme; - -import java.util.HashSet; -import java.util.UUID; - -import static com.ljmu.andre.GsonPreferences.Preferences.getExternalPath; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class FrameworkPreferencesDef extends ConstantDefiner { - /** - * =========================================================================== - * Booleans - * =========================================================================== - */ - public static final Preference ACCEPTED_TOS = new Preference( - "ACCEPTED_TOS", - false, Boolean.class - ); - public static final Preference SHOW_TUTORIAL = new Preference( - "SHOW_TUTORIAL", - true, Boolean.class - ); - public static final Preference HAS_SHOWN_REPKG_DIALOG = new Preference( - "HAS_SHOWN_REPKG_DIALOG", - false, Boolean.class - ); - public static final Preference SYSTEM_ENABLED = new Preference( - "SYSTEM_ENABLED", - true, Boolean.class - ); - public static final Preference CHECK_APK_UPDATES = new Preference( - "CHECK_APK_UPDATES", - true, Boolean.class - ); - public static final Preference CHECK_PACK_UPDATES = new Preference( - "CHECK_PACK_UPDATES", - true, Boolean.class - ); - public static final Preference CHECK_PACK_UPDATES_SC = new Preference( - "CHECK_PACK_UPDATES_SC", - true, Boolean.class - ); - public static final Preference KILL_SC_ON_CHANGE = new Preference( - "KILL_SC_ON_CHANGE", - true, Boolean.class - ); - public static final Preference SHOWN_ANDROID_P_WARNING = new Preference( - "SHOWN_ANDROID_P_WARNING", - false, Boolean.class - ); - public static final Preference NOTIFY_ON_LOAD = new Preference( - "NOTIFY_ON_LOAD", - true, Boolean.class - ); - public static final Preference RESIZE_SHARING_IMAGE = new Preference( - "RESIZE_SHARING_IMAGE", - true, Boolean.class - ); - public static final Preference LOCK_SHARING_RATIO = new Preference( - "LOCK_SHARING_RATIO", - true, Boolean.class - ); - public static final Preference BACK_OPENS_MENU = new Preference( - "BACK_OPENS_MENU", - false, Boolean.class - ); - public static final Preference SHOW_TRANSITION_ANIMATIONS = new Preference( - "SHOW_TRANSITION_ANIMATIONS", - true, Boolean.class - ); - public static final Preference SHARING_COMPRESS_VIDEOS = new Preference( - "SHARING_COMPRESS_VIDEOS", - true, Boolean.class - ); - public static final Preference SHOW_VIDEO_SHARING_ADVICE = new Preference( - "SHOW_VIDEO_SHARING_ADVICE", - true, Boolean.class - ); - public static final Preference SHOW_VIDEO_COMPRESSION_DIALOG = new Preference( - "SHOW_VIDEO_COMPRESSION_DIALOG", - true, Boolean.class - ); - public static final Preference HAS_SHOWN_PAY_MODEL_REASONING = new Preference( - "HAS_SHOWN_PAY_MODEL_REASONING", - false, Boolean.class - ); - - /** - * =========================================================================== - * Sets - * =========================================================================== - */ - public static final Preference DISABLED_MODULES = new Preference( - "DISABLED_MODULES", - new HashSet<>(), HashSet.class - ); - public static final Preference SELECTED_PACKS = new Preference( - "SELECTED_PACKS", - new HashSet<>(), HashSet.class - ); - public static final Preference SAVING_FILTER = new Preference( - "SAVING_FILTER", - new HashSet<>(), HashSet.class - ); - - /** - * =========================================================================== - * Strings - * =========================================================================== - */ - public static final Preference REPACKAGE_NAME = new Preference( - "REPACKAGE_NAME", - null, String.class - ); - /** - * Ability to save an old PackageName after App Repackaging to detect duplicates - */ - public static final Preference PLACE_HOLDER_UNINSTALL_REPKG = new Preference( - "PLACE_HOLDER_UNINSTALL_REPKG", - null, String.class - ); - public static final Preference CURRENT_THEME = new Preference( - "CURRENT_THEME", - UITheme.DEFAULT.getName(), String.class - ); - public static final Preference IGNORED_PACK_UPDATE_VERSION = new Preference( - "IGNORED_PACK_UPDATE_VERSION", - "", String.class - ); - public static final Preference LAST_BUILD_FLAVOUR = new Preference( - "LAST_BUILD_FLAVOUR", - BuildConfig.FLAVOR, String.class - ); - public static final Preference INSTALLATION_ID = new Preference( - "INSTALLATION_ID", - "", String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - String id = UUID.randomUUID().toString(); - putPref(preference, id); - return id; - } - }); - /** - * =========================================================================== - * FilePaths - * =========================================================================== - */ - public static final Preference CONTENT_PATH = new Preference( - "CONTENT_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getExternalPath() + "/" + STApplication.MODULE_TAG + "/"; - } - }); - public static final Preference CONTENT_DATA_PATH = new Preference( - "CONTENT_DATA_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "Data/"; - } - }); - public static final Preference DATABASES_PATH = new Preference( - "DATABASES_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "Databases/"; - } - }); - public static final Preference MODULES_PATH = new Preference( - "MODULES_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "ModulePacks/"; - } - }); - public static final Preference SHARED_IMAGE_PATH = new Preference( - "SHARED_IMAGE_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "SharedImages/"; - } - }); - public static final Preference DUMP_PATH = new Preference( - "DUMP_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "Dumps/"; - } - }); - public static final Preference TEMP_PATH = new Preference( - "TEMP_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "Temp/"; - } - }); - public static final Preference LOGS_PATH = new Preference( - "TEMP_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "ErrorLogs/"; - } - }); - public static final Preference CRASH_DUMP_PATH = new Preference( - "TEMP_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "CrashDumps/"; - } - }); - public static final Preference BACKUP_PATH = new Preference( - "BACKUP_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "Backups/"; - } - }); - public static final Preference TRANSLATIONS_PATH = new Preference( - "TRANSLATIONS_PATH", - null, String.class, new ConditionalCheck() { - @NonNull - @Override - protected Object performConditionCheck(Preference preference, Object preferenceVal) { - return getPref(CONTENT_PATH) + "Translations/"; - } - }); - /** - * =========================================================================== - * Longs - * =========================================================================== - */ - public static final Preference LAST_UPDATE_USER = new Preference( - "LAST_UPDATE_USER", - 0L, Long.class - ); - public static final Preference LAST_APK_UPDATE_CHECK = new Preference( - "LAST_APK_UPDATE_CHECK", - 0L, Long.class - ); - public static final Preference LAST_CHECK_PACKS = new Preference( - "LAST_CHECK_PACKS", - 0L, Long.class - ); - public static final Preference LAST_CHECK_SHOP = new Preference( - "LAST_CHECK_SHOP", - 0L, Long.class - ); - public static final Preference LAST_CHECK_FAQS = new Preference( - "LAST_CHECK_FAQS", - 0L, Long.class - ); - public static final Preference LAST_CHECK_FEATURES = new Preference( - "LAST_CHECK_FEATURES", - 0L, Long.class - ); - public static final Preference LAST_CHECK_TRANSLATIONS = new Preference( - "LAST_CHECK_TRANSLATIONS", - 0L, Long.class - ); - public static final Preference TRIAL_ACTIVE_TIME = new Preference( - "TRIAL_ACTIVE_TIME", - null, Long.class - ); - public static final Preference LAST_OPEN_APP = new Preference( - "LAST_OPEN_APP", - 0L, Long.class - ); - public static final Preference LAST_CHECK_REMOTE_CONFIG = new Preference( - "LAST_CHECK_REMOTE_CONFIG", - 0L, Long.class - ); - /** - * =========================================================================== - * Integers - * =========================================================================== - */ - @Deprecated - public static final Preference LENS_SELECTOR_SPAN = new Preference( - "LENS_SELECTOR_SPAN", - 4, Integer.class - ); - public static final Preference IGNORED_UPDATE_VERSION_CODE = new Preference( - "IGNORED_UPDATE_VERSION_CODE", - 0, Integer.class - ); - public static final Preference TRIAL_MODE = new Preference( - "TRIAL_MODE", - TrialUtils.TRIAL_UNKNOWN, Integer.class - ); - public static final Preference COMPRESSION_QUALITY = new Preference( - "COMPRESSION_QUALITY", - 3000, Integer.class - ); - public static final Preference LATEST_APK_VERSION_CODE = new Preference( - "LATEST_APK_VERSION_CODE", - Constants.getApkVersionCode(), Integer.class - ); - public static final Preference LATEST_PACK_VERSION_NAME = new Preference( - "LATEST_PACK_VERSION_NAME", - 0, Integer.class - ); - public static final Preference WATCHDOG_HANG_TIMEOUT = new Preference( - "WATCHDOG_HANG_TIMEOUT", - 10000, Integer.class - ); - public static Preference TRANSLATION_LOCALE = new Preference( - "TRANSLATION_LOCALE", - null, String.class - ); -} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/FrameworkPreferencesDef.kt b/app/src/main/java/com/ljmu/andre/snaptools/Utils/FrameworkPreferencesDef.kt new file mode 100644 index 0000000..759f619 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/FrameworkPreferencesDef.kt @@ -0,0 +1,268 @@ +package com.ljmu.andre.snaptools.Utils + +import com.jaqxues.akrolyb.prefs.Preference +import com.jaqxues.akrolyb.prefs.Types.Companion.genericType +import com.ljmu.andre.snaptools.BuildConfig +import com.ljmu.andre.snaptools.UIComponents.UITheme +import java.util.* +import kotlin.collections.HashSet + +/** + * This class was created by Andre R M (SID: 701439) + * It and its contents are free to use by all + */ +object FrameworkPreferencesDef { + /** + * =========================================================================== + * Booleans + * =========================================================================== + */ + @JvmField + val ACCEPTED_TOS = Preference( + "ACCEPTED_TOS", + false, Boolean::class.java + ) + @JvmField + val SHOW_TUTORIAL = Preference( + "SHOW_TUTORIAL", + true, Boolean::class.java + ) + @JvmField + val HAS_SHOWN_REPKG_DIALOG = Preference( + "HAS_SHOWN_REPKG_DIALOG", + false, Boolean::class.java + ) + @JvmField + val SYSTEM_ENABLED = Preference( + "SYSTEM_ENABLED", + true, Boolean::class.java + ) + @JvmField + val CHECK_APK_UPDATES = Preference( + "CHECK_APK_UPDATES", + true, Boolean::class.java + ) + @JvmField + val CHECK_PACK_UPDATES = Preference( + "CHECK_PACK_UPDATES", + true, Boolean::class.java + ) + @JvmField + val CHECK_PACK_UPDATES_SC = Preference( + "CHECK_PACK_UPDATES_SC", + true, Boolean::class.java + ) + @JvmField + val KILL_SC_ON_CHANGE = Preference( + "KILL_SC_ON_CHANGE", + true, Boolean::class.java + ) + @JvmField + val SHOWN_ANDROID_P_WARNING = Preference( + "SHOWN_ANDROID_P_WARNING", + false, Boolean::class.java + ) + @JvmField + val NOTIFY_ON_LOAD = Preference( + "NOTIFY_ON_LOAD", + true, Boolean::class.java + ) + @JvmField + val RESIZE_SHARING_IMAGE = Preference( + "RESIZE_SHARING_IMAGE", + true, Boolean::class.java + ) + @JvmField + val LOCK_SHARING_RATIO = Preference( + "LOCK_SHARING_RATIO", + true, Boolean::class.java + ) + @JvmField + val BACK_OPENS_MENU = Preference( + "BACK_OPENS_MENU", + false, Boolean::class.java + ) + @JvmField + val SHOW_TRANSITION_ANIMATIONS = Preference( + "SHOW_TRANSITION_ANIMATIONS", + true, Boolean::class.java + ) + val SHARING_COMPRESS_VIDEOS = Preference( + "SHARING_COMPRESS_VIDEOS", + true, Boolean::class.java + ) + @JvmField + val SHOW_VIDEO_SHARING_ADVICE = Preference( + "SHOW_VIDEO_SHARING_ADVICE", + true, Boolean::class.java + ) + @JvmField + val SHOW_VIDEO_COMPRESSION_DIALOG = Preference( + "SHOW_VIDEO_COMPRESSION_DIALOG", + true, Boolean::class.java + ) + @JvmField + val HAS_SHOWN_PAY_MODEL_REASONING = Preference( + "HAS_SHOWN_PAY_MODEL_REASONING", + false, Boolean::class.java + ) + + /** + * =========================================================================== + * Sets + * =========================================================================== + */ + @JvmField + val DISABLED_MODULES = Preference>( + "DISABLED_MODULES", + HashSet(), genericType>() + ) + @JvmField + val SELECTED_PACKS = Preference>( + "SELECTED_PACKS", + HashSet(), genericType>() + ) + val SAVING_FILTER = Preference>( + "SAVING_FILTER", + HashSet(), genericType>() + ) + + /** + * =========================================================================== + * Strings + * =========================================================================== + */ + @JvmField + val REPACKAGE_NAME = Preference( + "REPACKAGE_NAME", + null, String::class.java + ) + + /** + * Ability to save an old PackageName after App Repackaging to detect duplicates + */ + @JvmField + val PLACE_HOLDER_UNINSTALL_REPKG = Preference( + "PLACE_HOLDER_UNINSTALL_REPKG", + null, String::class.java + ) + @JvmField + val CURRENT_THEME = Preference( + "CURRENT_THEME", + UITheme.DEFAULT.getName(), String::class.java + ) + @JvmField + val IGNORED_PACK_UPDATE_VERSION = Preference( + "IGNORED_PACK_UPDATE_VERSION", + "", String::class.java + ) + val LAST_BUILD_FLAVOUR = Preference( + "LAST_BUILD_FLAVOUR", + BuildConfig.FLAVOR, String::class.java + ) + @JvmField + val INSTALLATION_ID = Preference( + "INSTALLATION_ID", + null, String::class.java) + + /** + * =========================================================================== + * Longs + * =========================================================================== + */ + val LAST_UPDATE_USER = Preference( + "LAST_UPDATE_USER", + 0L, Long::class.java + ) + @JvmField + val LAST_APK_UPDATE_CHECK = Preference( + "LAST_APK_UPDATE_CHECK", + 0L, Long::class.java + ) + @JvmField + val LAST_CHECK_PACKS = Preference( + "LAST_CHECK_PACKS", + 0L, Long::class.java + ) + @JvmField + val LAST_CHECK_SHOP = Preference( + "LAST_CHECK_SHOP", + 0L, Long::class.java + ) + @JvmField + val LAST_CHECK_FAQS = Preference( + "LAST_CHECK_FAQS", + 0L, Long::class.java + ) + @JvmField + val LAST_CHECK_FEATURES = Preference( + "LAST_CHECK_FEATURES", + 0L, Long::class.java + ) + @JvmField + val LAST_CHECK_TRANSLATIONS = Preference( + "LAST_CHECK_TRANSLATIONS", + 0L, Long::class.java + ) + @JvmField + val TRIAL_ACTIVE_TIME = Preference( + "TRIAL_ACTIVE_TIME", + null, Long::class.java + ) + @JvmField + val LAST_OPEN_APP = Preference( + "LAST_OPEN_APP", + 0L, Long::class.java + ) + @JvmField + val LAST_CHECK_REMOTE_CONFIG = Preference( + "LAST_CHECK_REMOTE_CONFIG", + 0L, Long::class.java + ) + + /** + * =========================================================================== + * Integers + * =========================================================================== + */ + @JvmField + @Deprecated("") + val LENS_SELECTOR_SPAN = Preference( + "LENS_SELECTOR_SPAN", + 4, Int::class.java + ) + @JvmField + val IGNORED_UPDATE_VERSION_CODE = Preference( + "IGNORED_UPDATE_VERSION_CODE", + 0, Int::class.java + ) + @JvmField + val TRIAL_MODE = Preference( + "TRIAL_MODE", + TrialUtils.TRIAL_UNKNOWN, Int::class.java + ) + @JvmField + val COMPRESSION_QUALITY = Preference( + "COMPRESSION_QUALITY", + 3000, Int::class.java + ) + @JvmField + val LATEST_APK_VERSION_CODE = Preference( + "LATEST_APK_VERSION_CODE", + Constants.getApkVersionCode(), Int::class.java + ) + val LATEST_PACK_VERSION_NAME = Preference( + "LATEST_PACK_VERSION_NAME", + 0, Int::class.java + ) + @JvmField + val WATCHDOG_HANG_TIMEOUT = Preference( + "WATCHDOG_HANG_TIMEOUT", + 10000, Int::class.java + ) + @JvmField + var TRANSLATION_LOCALE = Preference( + "TRANSLATION_LOCALE", + null, String::class.java + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt b/app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt new file mode 100644 index 0000000..93ca718 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt @@ -0,0 +1,42 @@ +package com.ljmu.andre.snaptools.Utils + +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 15.05.20 - Time 15:20. + * + * Allows to handle Events in multiple observers, without handling an Event twice + */ +abstract class EventObserver : Observer { + var lastChecked = 0 + final override fun onChanged(t: T) { + // Only handle event once + if (lastChecked == t.hashCode()) + return + handleEvent(t) + lastChecked = t.hashCode() + } + + abstract fun handleEvent(t: T) +} + +inline fun LiveData.addEventObserver(lifecycleOwner: LifecycleOwner, crossinline handler: (T) -> Unit) { + observe(lifecycleOwner, object: EventObserver() { + override fun handleEvent(t: T) { + handler(t) + } + }) +} + +inline fun LiveData.consumeResult(crossinline action: (T) -> Unit) { + observeForever(object: Observer { + override fun onChanged(t: T) { + removeObserver(this) + action(t) + } + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/PackUtils.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/PackUtils.java index b426b09..26256f8 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/PackUtils.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/PackUtils.java @@ -12,6 +12,7 @@ import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; import com.google.common.io.Files; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Exceptions.NullObjectException; import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData; import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData; @@ -39,10 +40,9 @@ import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getCreateDir; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.ljmu.andre.snaptools.Utils.FileUtils.getCreateDir; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.LAST_CHECK_PACKS; -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.MODULES_PATH; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS; import static com.ljmu.andre.snaptools.Utils.MiscUtils.calcTimeDiff; @@ -122,7 +122,7 @@ public static boolean isPackInstalled(String packName) { @Nullable public static Map getInstalledMetaData() { try { - File packDirectory = new File((String) getPref(MODULES_PATH)); + File packDirectory = new File(PathProvider.getModulesPath()); File[] jarFileList = packDirectory.listFiles((file, s) -> s.endsWith(".jar")); @@ -140,7 +140,7 @@ public static Map getInstalledMetaData() { for (File file : jarFileList) { try { - LocalPackMetaData packMetaData = getPackMetaData(file); + LocalPackMetaData packMetaData = getPackMetaData(file, PackEventRequest.EventHandler.ignoreEvents); packMetaDataMap.put(packMetaData.getName(), packMetaData); } catch (Throwable t) { Timber.e(t); @@ -158,8 +158,8 @@ public static Map getInstalledMetaData() { return null; } - public static LocalPackMetaData getPackMetaData(File file) throws NullObjectException { - LocalPackMetaData packMetaData = new LocalPackMetaData(); + public static LocalPackMetaData getPackMetaData(File file, PackEventRequest.EventHandler dispatcher) throws NullObjectException { + LocalPackMetaData packMetaData = new LocalPackMetaData(dispatcher); bindPackMetaData(packMetaData, file); return packMetaData; } @@ -193,7 +193,7 @@ public static String getFlavourFromAttributes(Attributes attributes, File file) public static Observable> getAllMetaData() { Callable> callable = () -> { - File packDirectory = new File((String) getPref(MODULES_PATH)); + File packDirectory = new File(PathProvider.getModulesPath()); File[] jarFileList = packDirectory.listFiles((file, s) -> s.endsWith(".jar")); @@ -205,9 +205,9 @@ public static Observable> getAllMetaData() { for (File file : jarFileList) { LocalPackMetaData metaData; try { - metaData = getPackMetaData(file); + metaData = getPackMetaData(file, PackEventRequest.EventHandler.ignoreEvents); } catch (Throwable t) { - metaData = (LocalPackMetaData) new FailedPackMetaData() + metaData = (LocalPackMetaData) new FailedPackMetaData(PackEventRequest.EventHandler.ignoreEvents) .setReason(t.getMessage()) .setName(file.getName().replace(".jar", "")) .completedBinding(); @@ -220,7 +220,7 @@ public static Observable> getAllMetaData() { for (String packName : selectedPacks) { if (!packMetaDataMap.containsKey(packName)) { - FailedPackMetaData metaData = (FailedPackMetaData) new FailedPackMetaData() + FailedPackMetaData metaData = (FailedPackMetaData) new FailedPackMetaData(PackEventRequest.EventHandler.ignoreEvents) .setReason("Pack is enabled but cannot be found in the installed list") .setName(packName) .completedBinding(); @@ -238,7 +238,7 @@ public static Observable> getAllMetaData() { } public static Long timeSinceLastPackCheck() { - return System.currentTimeMillis() - (Long) getPref(LAST_CHECK_PACKS); + return System.currentTimeMillis() - getPref(LAST_CHECK_PACKS); } @Nullable @@ -251,19 +251,19 @@ public static String generatePacksChecksum() { ExecutorService executor = Executors.newCachedThreadPool(); for (String selectedPack : selectPackSet) { - Timber.d("Hashing Pack: " + selectedPack); - File packDir = getCreateDir(MODULES_PATH); + Timber.d("Hashing Pack: %s", selectedPack); + File packDir = getCreateDir(PathProvider.getModulesPath()); File modulePackFile = new File(packDir, selectedPack + ".jar"); if (!modulePackFile.exists()) { - Timber.d("Pack file doesn't exist: " + modulePackFile); + Timber.d("Pack file doesn't exist: %s", modulePackFile); continue; } executor.execute(() -> { try { HashCode packHash = Files.hash(modulePackFile, Hashing.murmur3_128(6782590)); - Timber.d("Pack Hash: " + packHash); + Timber.d("Pack Hash: %s", packHash); synchronized (PACK_CHECKSUM_LOCK) { packHashCodeList.add( diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/PathProvider.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/PathProvider.java new file mode 100644 index 0000000..77d935d --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/PathProvider.java @@ -0,0 +1,182 @@ +package com.ljmu.andre.snaptools.Utils; + +import android.os.Build; +import android.os.Environment; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import com.ljmu.andre.snaptools.STApplication; +import timber.log.Timber; + +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 18.05.20 - Time 21:45. + */ +public class PathProvider { + private static String cachedExternalDir; + + public static String getContentPath() { + return getExternalPath() + "/" + STApplication.MODULE_TAG + "/"; + } + + public static String getContentDataPath() { + return getContentPath() + "Data/"; + } + + public static String getDatabasesPath() { + return getContentPath() + "Databases/"; + } + + public static String getModulesPath() { + return getContentPath() + "ModulePack/"; + } + + public static String getSharedImagePath() { + return getContentPath() + "SharedImages/"; + } + + public static String getDumpPath() { + return getContentPath() + "Dumps/"; + } + + public static String getTempPath() { + return getContentPath() + "Temp/"; + } + + public static String getLogsPath() { + return getContentPath() + "ErrorLogs/"; + } + + public static String getCrashDumpPath() { + return getContentPath() + "CrashDumps/"; + } + + public static String getBackupPath() { + return getContentPath() + "Backups/"; + } + + public static String getTranslationsPath() { + return getContentPath() + "Translations/"; + } + + public static String getExternalPath() { + if (cachedExternalDir != null) + return cachedExternalDir; + + cachedExternalDir = useExternalPathFallback(); + + if (cachedExternalDir != null) + return cachedExternalDir; + + try { + cachedExternalDir = new MethodTimeout() { + @Override + public String call() throws Exception { + String externalPath = null; + HashSet externalPathSet = getExternalMounts(); + + if (!externalPathSet.isEmpty()) { + for (String externalMount : externalPathSet) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + externalPath = externalMount; + break; + } else { + if (isMounted(externalMount)) { + return externalMount; + } + } + } + } + + if (externalPath == null) + externalPath = useExternalPathFallback(); + + if (externalPath != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && + isMounted(externalPath)) + return externalPath; + } + + return null; + } + }.runWithTimeout(5, TimeUnit.SECONDS); + } catch (Exception e) { + Timber.e(e); + } + + if (cachedExternalDir != null) + return cachedExternalDir; + + throw new IllegalStateException("Mounted storage not found"); + } + + @NonNull + private static HashSet getExternalMounts() { + HashSet out = new HashSet<>(); + String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; + String s = ""; + try { + Process process = new ProcessBuilder().command("mount") + .redirectErrorStream(true).start(); + process.waitFor(); + InputStream is = process.getInputStream(); + byte[] buffer = new byte[1024]; + while (is.read(buffer) != -1) { + s = s + new String(buffer); + } + is.close(); + } catch (Exception e) { + Timber.e(e); + } + + // parse output + String[] lines = s.split("\n"); + for (String line : lines) { + if (!line.toLowerCase(Locale.US).contains("asec")) { + if (line.matches(reg)) { + String[] parts = line.split(" "); + for (String part : parts) { + if (part.startsWith("/")) + if (!part.toLowerCase(Locale.US).contains("vold")) + out.add(part); + } + } + } + } + + return out; + } + + @Nullable + private static String useExternalPathFallback() { + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + try { + Class environment_cls = Class.forName("android.os.Environment"); + Method setUserRequiredM = environment_cls.getMethod("setUserRequired", boolean.class); + setUserRequiredM.invoke(null, false); + } catch (Exception e) { + Timber.e(e, "Get external path exception"); + } + } + + if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) + return null; + + return Environment.getExternalStorageDirectory().getAbsolutePath(); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static boolean isMounted(String path) { + return Environment.MEDIA_MOUNTED.equals( + Environment.getExternalStorageState(new File(path)) + ); + } +} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/PreferenceHelpers.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/PreferenceHelpers.java index 454cde0..cdb755c 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/PreferenceHelpers.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/PreferenceHelpers.java @@ -3,14 +3,14 @@ import android.app.Activity; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.jaqxues.akrolyb.prefs.Preference; -import com.ljmu.andre.GsonPreferences.Preferences.Preference; import java.util.Collection; import java.util.Map; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.KILL_SC_ON_CHANGE; /** @@ -25,19 +25,14 @@ public static boolean togglePreference(@NonNull Preference preference) { return newValue; } - public static void addToCollection(Preference preference, Object object) { + public static void addToCollection(Preference> preference, T object) { addToCollection(preference, object, null); } - public static void addToCollection(Preference preference, Object object, @Nullable Activity shouldKill) { - - Collection collection = getPref(preference); - if (collection == null) - collection = preference.getDefaultVal(); - + public static void addToCollection(Preference> preference, T object, @Nullable Activity shouldKill) { + Collection collection = getPref(preference); collection.add(object); - update(preference, collection, shouldKill); } @@ -48,34 +43,31 @@ private static void update(Preference preference, Object newObject, @Nullable Ac putPref(preference, newObject); } - public static void putAndKill(Preference preference, Object object, Activity activity) { + public static void putAndKill(Preference preference, T object, Activity activity) { putPref(preference, object); if (getPref(KILL_SC_ON_CHANGE)) PackUtils.killSCService(activity); } - public static void removeFromMap(Preference preference, Object key) { + public static void removeFromMap(Preference> preference, K key) { addToMap(preference, key, null); } - public static void addToMap(Preference preference, Object key, Object value) { + public static void addToMap(Preference> preference, K key, V value) { addToMap(preference, key, value, null); } - public static void addToMap(Preference preference, Object key, Object value, @Nullable Activity shouldKill) { - Map map = getPref(preference); - - if (map == null) - map = preference.getDefaultVal(); + public static void addToMap(Preference> preference, K key, V value, @Nullable Activity shouldKill) { + Map map = getPref(preference); map.put(key, value); update(preference, map, shouldKill); } - public static void removeFromMap(Preference preference, Object key, @Nullable Activity shouldKill) { - Map map = getPref(preference); + public static void removeFromMap(Preference> preference, K key, @Nullable Activity shouldKill) { + Map map = getPref(preference); if (map == null) return; @@ -83,30 +75,30 @@ public static void removeFromMap(Preference preference, Object key, @Nullable Ac update(preference, map, shouldKill); } - public static boolean mapContainsKey(Preference preference, Object key) { - Map map = getPref(preference); + public static boolean mapContainsKey(Preference> preference, K key) { + Map map = getPref(preference); return map != null && map.containsKey(key); } - public static boolean mapContainsValue(Preference preference, Object key) { - Map map = getPref(preference); + public static boolean mapContainsValue(Preference> preference, K key) { + Map map = getPref(preference); return map != null && map.containsValue(key); } - public static T getFromMap(Preference preference, Object key) { - Map map = getPref(preference); + public static V getFromMap(Preference> preference, K key) { + Map map = getPref(preference); if (map == null) return null; - return (T) map.get(key); + return map.get(key); } - public static void removeFromCollection(Preference preference, Object object) { + public static void removeFromCollection(Preference> preference, T object) { removeFromCollection(preference, object, null); } - public static void removeFromCollection(Preference preference, Object object, @Nullable Activity shouldKill) { - Collection collection = getPref(preference); + public static void removeFromCollection(Preference> preference, T object, @Nullable Activity shouldKill) { + Collection collection = getPref(preference); if (collection == null) return; @@ -114,8 +106,8 @@ public static void removeFromCollection(Preference preference, Object object, @N update(preference, collection, shouldKill); } - public static boolean collectionContains(Preference preference, Object object) { - Collection collection = getPref(preference); + public static boolean collectionContains(Preference> preference, T object) { + Collection collection = getPref(preference); return collection != null && collection.contains(object); } } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java deleted file mode 100644 index 0326c2c..0000000 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ljmu.andre.snaptools.Utils; - -import com.google.common.base.MoreObjects; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class Result { - private K key; - private V value; - - public Result(K key, V value) { - this.key = key; - this.value = value; - } - - public K getKey() { - return key; - } - - public Result setKey(K key) { - this.key = key; - return this; - } - - public V getValue() { - return value; - } - - public Result setValue(V value) { - this.value = value; - return this; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .omitNullValues() - .add("key", key == null ? null : key.toString()) - .add("value", value == null ? null : value.toString()) - .toString(); - } - - public static class BooleanResult extends Result { - public BooleanResult(Boolean key, T value) { - super(key, value); - } - } - - public static class BadResult extends BooleanResult { - public BadResult(String value) { - super(false, value); - } - } - - public static class GoodResult extends BooleanResult { - public GoodResult(String value) { - super(true, value); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt new file mode 100644 index 0000000..13d6125 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt @@ -0,0 +1,26 @@ +package com.ljmu.andre.snaptools.Utils + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 14:20. + */ + +sealed class Result { + data class Success(val data: T) : Result() + data class Error(val exception: Exception) : Result() +} + +sealed class Request { + object Pending : Request() + class Loaded(val result: Result) : Request() +} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/TimberUtils.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/TimberUtils.java index 3f801e6..4cd39fe 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/TimberUtils.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/TimberUtils.java @@ -3,11 +3,8 @@ import androidx.annotation.NonNull; import android.util.Log; -import com.ljmu.andre.ErrorLogger.ErrorLogger; import com.ljmu.andre.snaptools.STApplication; -import java.util.HashSet; - import de.robv.android.xposed.XposedBridge; import timber.log.Timber; import timber.log.Timber.DebugTree; @@ -47,43 +44,6 @@ protected String createStackElementTag(@NonNull StackTraceElement element) { }, "Debug"); } else { plantCheck(new ReleaseTree(), "Release"); - Timber.plant(new ReporterTree()); - } - } - - private static class ReporterTree extends ReleaseTree { - private static final HashSet priorityWhitelist; - - static { - priorityWhitelist = new HashSet<>(); - priorityWhitelist.add(Log.WARN); - priorityWhitelist.add(Log.ERROR); - priorityWhitelist.add(Log.ASSERT); - } - - @Override - protected boolean isLoggable(String tag, int priority) { - return priority >= Log.WARN; - } - - @Override - protected void log(int priority, String tag, String message, Throwable t) { -// if (message != null && priority >= Log.INFO -// && Fabric.isInitialized() && Crashlytics.getInstance() != null) { -// Crashlytics.doLog(priority, tag, message); -// } - - if (isLoggable(tag, priority)) { - ErrorLogger errorLogger = ErrorLogger.getInstance(); - - if (message != null && errorLogger != null) { - errorLogger.addError(priority, message); - } - -// if (t != null && priority == Log.ERROR && Fabric.isInitialized() && Crashlytics.getInstance() != null) { -// Crashlytics.logException(t); -// } - } } } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/TrialUtils.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/TrialUtils.java index 074e9c4..17e8410 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/TrialUtils.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/TrialUtils.java @@ -17,8 +17,8 @@ import timber.log.Timber; -import static com.ljmu.andre.GsonPreferences.Preferences.getPref; -import static com.ljmu.andre.GsonPreferences.Preferences.putPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.getPref; +import static com.jaqxues.akrolyb.prefs.PrefManagerKt.putPref; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.TRIAL_ACTIVE_TIME; import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.TRIAL_MODE; diff --git a/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt new file mode 100644 index 0000000..aeb3147 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt @@ -0,0 +1,200 @@ +package com.ljmu.andre.snaptools.repository + +import android.app.Activity +import androidx.annotation.WorkerThread +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.jaqxues.akrolyb.prefs.Preference +import com.jaqxues.akrolyb.prefs.getPref +import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent.DownloadState +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest +import com.ljmu.andre.snaptools.EventBus.Events.PackUnloadEvent +import com.ljmu.andre.snaptools.Framework.FrameworkManager +import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData +import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState +<<<<<<< HEAD +import com.ljmu.andre.snaptools.Networking.Helpers.DownloadModulePack +import com.ljmu.andre.snaptools.Networking.Helpers.GetPackChangelog +import com.ljmu.andre.snaptools.Networking.Helpers.GetServerPacks +import com.ljmu.andre.snaptools.Networking.Packets.PackDataPacket +import com.ljmu.andre.snaptools.Networking.WebResponse +import com.ljmu.andre.snaptools.Utils.* +======= +>>>>>>> parent of 472732d... PackDownloaderFragment.java to PackDownloaderFragment.kt +import com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS +import com.ljmu.andre.snaptools.Utils.PackUtils.getPackMetaData +import com.ljmu.andre.snaptools.Utils.PathProvider +import com.ljmu.andre.snaptools.Utils.PreferenceHelpers +import com.ljmu.andre.snaptools.Utils.Result +import timber.log.Timber +import java.io.File +import java.util.HashSet + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 10:01. + */ +class PackRepository { + // Private Mutable LiveData + private val _eventDispatcher = MutableLiveData() + private val _localMetadata = MutableLiveData>() +<<<<<<< HEAD + private val _remoteMetadata = MutableLiveData>>() + +======= +>>>>>>> parent of 472732d... PackDownloaderFragment.java to PackDownloaderFragment.kt + // Exposed public LiveData + val eventDispatcher: LiveData = _eventDispatcher + val localMetadata: LiveData> = _localMetadata + + private val packDirectory = File(PathProvider.getModulesPath()) + + fun refreshLocalMetadata(evtHandler: PackEventRequest.EventHandler) { + val jarFileList = packDirectory.listFiles { _, name -> name.endsWith(".jar") } + if (jarFileList.isNullOrEmpty()) { + _localMetadata.postValue(emptyList()) + return + } + + val packs = jarFileList.associate { file -> + val metadata = try { + getPackMetaData(file, evtHandler) + } catch (t: Throwable) { + FailedPackMetaData(evtHandler).run { + reason = t.message + name = file.name.replace(".jar", "") + completedBinding() + } + } + metadata.name to metadata + } + + val packsList = packs.values.toMutableList() + + // Selected Packs that have been deleted or cannot be found for some reason + SELECTED_PACKS.getPref().forEach { packName -> + if (packName in packs) return@forEach + + val failedMetadata = FailedPackMetaData(evtHandler).run { + reason = "Pack is enabled but cannot be found in the installed list" + name = packName + completedBinding() + } + packsList.add(failedMetadata) + } + + _localMetadata.postValue(packsList.sorted()) + } + + fun unloadPack(packName: String, activity: Activity): Result { + val modPack = FrameworkManager.getModulePack(packName) + if (modPack == null) { + val e = IllegalStateException("Pack was not loaded. Could not unload it") + Timber.e(e) + return Result.Error(e) + } + if (FrameworkManager.unloadModPack(packName)) { + _eventDispatcher.value = PackUnloadEvent(modPack.packMetaData) + return Result.Success(packName) + } + return Result.Error(Exception("Unknown Exception while trying to unload the Pack $packName")) + } + + fun disablePack(packName: String, activity: Activity): Result { + val result = unloadPack(packName, activity) + if (result is Result.Error) + return result + FrameworkManager.disableModPack(packName) + return Result.Success(packName) + } + + /** + * Unloads, disables and deletes the pack + */ + fun deletePack(packName: String, activity: Activity, evtHandler: PackEventRequest.EventHandler): Result { + val result = disablePack(packName, activity) + if (result is Result.Error) + return result + FrameworkManager.deleteModPack(packName, activity) + + if (PreferenceHelpers.collectionContains(SELECTED_PACKS, packName)) { + val e = IllegalStateException("Failed to delete Pack $packName") + Timber.e(e) + return Result.Error(e) + } + _eventDispatcher.value = PackDeleteEvent(packName) + refreshLocalMetadata(evtHandler) + return Result.Success(packName) + } + + /** + * Download Pack and update LiveData + */ + fun downloadPack(activity: Activity, metaData: ServerPackMetaData) { + val download = metaData.run { + DownloadModulePack( + activity, + name, scVersion, type, isDeveloper, packVersion, flavour + ) + } + download.download { state, message, outputFile, responseCode -> + _eventDispatcher.postValue( + PackDownloadEvent() + .setState(if (state) DownloadState.SUCCESS else DownloadState.FAIL) + .setMessage(message) + .setMetaData(metaData) + .setOutputFile(outputFile) + .setResponseCode(responseCode) + ) + } + } + + fun setTutorialPacks() { + _localMetadata.value = + listOf("10.0.0.0", "10.1.0.1", "10.12.1.0", "10.16.0.0").map { + LocalPackMetaData.getTutorialPack(it) + } + } + + fun clear() { + _localMetadata.value = emptyList() + } + + @WorkerThread + fun enablePack(packName: String, activity: Activity) { + PreferenceHelpers.addToCollection(SELECTED_PACKS, packName, activity) + val packLoadEvent = FrameworkManager.loadModPack(activity, packName, PackLoadState(packName)) + _eventDispatcher.postValue(packLoadEvent) + } +<<<<<<< HEAD + + @WorkerThread + fun getChangelog(activity: Activity, pack: ServerPackMetaData, liveData: MutableLiveData>) { + liveData.postValue(Request.Pending) + GetPackChangelog.performCheck( + activity, + pack.type, + pack.scVersion, + pack.flavour, + object : WebResponse.PacketResultListener { + override fun success(message: String, packet: PackDataPacket) { + Timber.d(message) + liveData.postValue(Request.Loaded(Result.Success(packet))) + } + + override fun error(message: String, t: Throwable?, errorCode: Int) { + Timber.e(t, message) + liveData.postValue(Request.Loaded(Result.Error(PacketResultException( + "Issue Getting Changelog", + message, errorCode + )))) + } + } + ) + } +======= +>>>>>>> parent of 472732d... PackDownloaderFragment.java to PackDownloaderFragment.kt +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt b/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt new file mode 100644 index 0000000..541e8f8 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt @@ -0,0 +1,74 @@ +package com.ljmu.andre.snaptools.viewmodel + +import android.app.Activity +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest +import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData +import com.ljmu.andre.snaptools.Utils.Result +import com.ljmu.andre.snaptools.repository.PackRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 10:40. + */ +class PackViewModel : ViewModel() { + val localMetadata: LiveData> + get() = packRepo.localMetadata + + fun refreshLocalPacks(eventHandler: PackEventRequest.EventHandler) { + viewModelScope.launch(Dispatchers.IO) { + packRepo.refreshLocalMetadata(eventHandler) + } + } + + fun setTutorialPacks() { + packRepo.setTutorialPacks() + } + + fun clearPacks() { + packRepo.clear() + } + + fun getInfoFromName(packName: String): Pair? { + val packs = localMetadata.value + return packs?.find { it.name == packName }?.let { + it to packs.indexOf(it) + } + } + + fun enablePack(packName: String, activity: Activity): LiveData> { + val liveData = MutableLiveData>() + viewModelScope.launch(Dispatchers.Default) { + liveData.postValue( + try { + packRepo.enablePack(packName, activity) + Result.Success(packName) + } catch (e: Exception) { + Timber.e(e, "Could not load Pack") + Result.Error(e) + }) + } + return liveData + } + + fun unloadPack(packName: String, activity: Activity) = packRepo.unloadPack(packName, activity) + + fun deletePack(packName: String, activity: Activity, evtHandler: PackEventRequest.EventHandler) = packRepo.deletePack(packName, activity, evtHandler) + + fun downloadPack(activity: Activity, metadata: ServerPackMetaData) { + viewModelScope.launch(Dispatchers.IO) { + packRepo.downloadPack(activity, metadata) + } + } + + companion object { + private val packRepo by lazy { PackRepository() } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_hang_error.xml b/app/src/main/res/layout/activity_hang_error.xml deleted file mode 100644 index d676a4a..0000000 --- a/app/src/main/res/layout/activity_hang_error.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - -