mirror of
https://github.com/whyorean/AuroraStore.git
synced 2026-06-19 04:58:47 -04:00
UI : Redesign app [1/2]
Addressed following bugs: https://gitlab.com/AuroraOSS/AuroraStore/issues/253 https://gitlab.com/AuroraOSS/AuroraStore/issues/237 https://gitlab.com/AuroraOSS/AuroraStore/issues/259 https://gitlab.com/AuroraOSS/AuroraStore/issues/257 https://gitlab.com/AuroraOSS/AuroraStore/issues/255 https://gitlab.com/AuroraOSS/AuroraStore/issues/251 https://gitlab.com/AuroraOSS/AuroraStore/issues/249 https://gitlab.com/AuroraOSS/AuroraStore/issues/234 https://gitlab.com/AuroraOSS/AuroraStore/issues/247 https://gitlab.com/AuroraOSS/AuroraStore/issues/232
This commit is contained in:
@@ -197,4 +197,4 @@ While *Aurora Store* was originally based on Sergei Yeriomin's [Yalp store](http
|
||||
* [Raccoon](https://github.com/onyxbits/raccoon4)
|
||||
* [SAI](https://github.com/Aefyr/SAI)
|
||||
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/packages/com.dragons.aurora/) [<img src="https://poeditor.com/public/images/logo_small.png" alt="Join POEditor">](https://poeditor.com/join/project/54swaCpFXJ)
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/packages/com.dragons.aurora/) [<img src="https://poeditor.com/public/images/logo_small.png" alt="Join POEditor">](https://poeditor.com/join/project/54swaCpFXJ)
|
||||
|
||||
@@ -42,7 +42,9 @@ android {
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
minifyEnabled true
|
||||
zipAlignEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
@@ -52,19 +54,7 @@ android {
|
||||
sourceCompatibility 1.8
|
||||
}
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
def requested = details.requested
|
||||
if (requested.group == "androidx") {
|
||||
if (!requested.name.startsWith("multidex")) {
|
||||
details.useVersion "${targetSdk}.+"
|
||||
}
|
||||
}
|
||||
warning 'MissingTranslation', 'GetLocales', 'VectorDrawableCompat'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,12 +62,19 @@ dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'commons-io:commons-io:2.6'
|
||||
implementation 'org.apache.maven:maven-artifact:3.6.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
|
||||
|
||||
//UI-Libs
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.1.0-alpha10'
|
||||
implementation 'androidx.palette:palette:1.0.0'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.1.0'
|
||||
implementation 'androidx.navigation:navigation-ui:2.1.0'
|
||||
implementation 'com.google.android.material:material:1.1.0-alpha10'
|
||||
implementation 'io.github.luizgrp.sectionedrecyclerviewadapter:sectionedrecyclerviewadapter:3.0.0'
|
||||
|
||||
//Utils
|
||||
implementation 'androidx.annotation:annotation:1.1.0'
|
||||
implementation 'org.apache.commons:commons-text:1.8'
|
||||
@@ -85,18 +82,23 @@ dependencies {
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
compileOnly 'org.projectlombok:lombok:1.18.10'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.10'
|
||||
|
||||
//PlayStoreApi
|
||||
implementation 'com.github.whyorean:playstore-api-v2:2.4'
|
||||
|
||||
//OkHTTP3
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
|
||||
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.2.2'
|
||||
|
||||
//RX-Java2
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.2.14'
|
||||
implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.1'
|
||||
|
||||
//ButterKnife
|
||||
implementation 'com.jakewharton:butterknife:10.2.0'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0'
|
||||
|
||||
//Glide
|
||||
implementation 'com.github.bumptech.glide:glide:4.10.0'
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:4.10.0"
|
||||
|
||||
4
app/proguard-rules.pro
vendored
4
app/proguard-rules.pro
vendored
@@ -51,4 +51,6 @@
|
||||
# is used to reflectively look up the generated ViewBinding.
|
||||
-keep class butterknife.*
|
||||
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
|
||||
-keepclasseswithmembernames class * { @butterknife.* <fields>; }
|
||||
-keepclasseswithmembernames class * { @butterknife.* <fields>; }
|
||||
|
||||
-keep public class com.aurora.store.ui.preference.fragment.*
|
||||
@@ -67,34 +67,12 @@
|
||||
tools:targetApi="q">
|
||||
|
||||
<activity
|
||||
android:name=".activity.AuroraActivity"
|
||||
android:name=".ui.main.AuroraActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="search"
|
||||
android:scheme="market" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.DetailsActivity"
|
||||
android:name=".ui.details.DetailsActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
@@ -121,36 +99,61 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.FullscreenImageActivity"
|
||||
android:name=".ui.single.activity.FullscreenImageActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale" />
|
||||
<activity
|
||||
android:name=".activity.DownloadsActivity"
|
||||
android:name=".ui.single.activity.DownloadsActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale" />
|
||||
<activity
|
||||
android:name=".activity.AccountsActivity"
|
||||
android:name=".ui.accounts.AccountsActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale" />
|
||||
<activity
|
||||
android:name=".activity.SettingsActivity"
|
||||
android:name=".ui.preference.SettingsActivity"
|
||||
android:configChanges="locale|orientation|fontScale"
|
||||
android:theme="@style/AppTheme" />
|
||||
<activity
|
||||
android:name=".activity.IntroActivity"
|
||||
android:name=".ui.intro.IntroActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale" />
|
||||
<activity
|
||||
android:name=".activity.ManualDownloadActivity"
|
||||
android:name=".ui.single.activity.ManualDownloadActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale" />
|
||||
<activity
|
||||
android:name=".activity.DeviceInfoActivity"
|
||||
android:name=".ui.single.activity.DeviceInfoActivity"
|
||||
android:configChanges="keyboardHidden|locale|orientation|fontScale" />
|
||||
<activity
|
||||
android:name=".activity.GoogleLoginActivity"
|
||||
android:theme="@style/LoginTheme" />
|
||||
<activity android:name=".ui.single.activity.GoogleLoginActivity" />
|
||||
<activity android:name=".ui.single.activity.SplashActivity">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.search.activity.SearchActivity"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="search"
|
||||
android:scheme="market" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ui.search.activity.SearchResultActivity" />
|
||||
<activity android:name=".ui.category.CategoryAppsActivity" />
|
||||
<activity android:name=".ui.installed.InstalledAppActivity" />
|
||||
<activity android:name=".ui.single.activity.GenericActivity" />
|
||||
<activity android:name=".ui.devapps.DevAppsActivity" />
|
||||
<activity android:name=".ui.details.ReviewsActivity" />
|
||||
|
||||
<provider
|
||||
android:name=".provider.AuroraSuggestionProvider"
|
||||
android:authorities="com.aurora.store.provider.AuroraSuggestionProvider"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.aurora.store.fileProvider"
|
||||
@@ -177,11 +180,7 @@
|
||||
|
||||
<service android:name=".installer.InstallerService" />
|
||||
<service android:name=".SelfUpdateService" />
|
||||
<service android:name=".AnonymousLoginService" />
|
||||
|
||||
<meta-data
|
||||
android:name="preloaded_fonts"
|
||||
android:resource="@array/preloaded_fonts" />
|
||||
<service android:name=".ValidateApiService" />
|
||||
<service android:name=".BulkUpdateService" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.aurora.store;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.events.Event;
|
||||
import com.aurora.store.events.Events;
|
||||
import com.aurora.store.events.RxBus;
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.Log;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class AnonymousLoginService extends Service {
|
||||
|
||||
public static AnonymousLoginService instance = null;
|
||||
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
public static boolean isServiceRunning() {
|
||||
try {
|
||||
return instance != null && instance.isRunning();
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRunning() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
login();
|
||||
}
|
||||
|
||||
private void login() {
|
||||
disposable.add(Observable.fromCallable(() -> PlayStoreApiAuthenticator
|
||||
.login(this))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((api) -> {
|
||||
if (api != null) {
|
||||
Log.i("Anonymous Login Successful");
|
||||
Accountant.setAnonymous(this, true);
|
||||
RxBus.publish(new Event(Events.LOGGED_IN));
|
||||
} else
|
||||
Log.e("Anonymous Login Failed Permanently");
|
||||
destroyService();
|
||||
}, err -> {
|
||||
Log.e(err.getMessage());
|
||||
destroyService();
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
instance = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void destroyService() {
|
||||
Log.e("Anonymous login service destroyed");
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
37
app/src/main/java/com/aurora/store/AppDiffCallback.java
Normal file
37
app/src/main/java/com/aurora/store/AppDiffCallback.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.aurora.store;
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
import com.aurora.store.model.App;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AppDiffCallback extends DiffUtil.Callback {
|
||||
private List<App> newList;
|
||||
private List<App> oldList;
|
||||
|
||||
public AppDiffCallback(List<App> newList, List<App> oldList) {
|
||||
this.newList = newList;
|
||||
this.oldList = oldList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOldListSize() {
|
||||
return oldList != null ? oldList.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize() {
|
||||
return newList != null ? newList.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldIndex, int newIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldIndex, int newIndex) {
|
||||
return oldList.get(oldIndex).equals(newList.get(newIndex));
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,15 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Application;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import com.aurora.store.events.Event;
|
||||
import com.aurora.store.events.RxBus;
|
||||
import com.aurora.store.installer.Installer;
|
||||
import com.aurora.store.installer.InstallerService;
|
||||
import com.aurora.store.installer.Uninstaller;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -38,20 +42,27 @@ import io.reactivex.plugins.RxJavaPlugins;
|
||||
|
||||
public class AuroraApplication extends Application {
|
||||
|
||||
public static boolean updating = false;
|
||||
public static List<App> ongoingUpdateList = new ArrayList<>();
|
||||
public static GooglePlayAPI api = null;
|
||||
|
||||
private static RxBus rxBus = null;
|
||||
private static boolean bulkUpdateAlive = false;
|
||||
private static List<App> ongoingUpdateList = new ArrayList<>();
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static Installer installer;
|
||||
private static Installer installer;
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static Uninstaller uninstaller;
|
||||
private static Uninstaller uninstaller;
|
||||
|
||||
public static boolean getOnGoingUpdate() {
|
||||
return updating;
|
||||
public static RxBus getRxBus() {
|
||||
return rxBus;
|
||||
}
|
||||
|
||||
public static void setOnGoingUpdate(boolean updating) {
|
||||
AuroraApplication.updating = updating;
|
||||
public static boolean isBulkUpdateAlive() {
|
||||
return bulkUpdateAlive;
|
||||
}
|
||||
|
||||
public static void setBulkUpdateAlive(boolean updating) {
|
||||
AuroraApplication.bulkUpdateAlive = updating;
|
||||
}
|
||||
|
||||
public static List<App> getOngoingUpdateList() {
|
||||
@@ -69,7 +80,7 @@ public class AuroraApplication extends Application {
|
||||
iterator.remove();
|
||||
}
|
||||
if (ongoingUpdateList.isEmpty())
|
||||
setOnGoingUpdate(false);
|
||||
setBulkUpdateAlive(false);
|
||||
}
|
||||
|
||||
public static Installer getInstaller() {
|
||||
@@ -80,24 +91,35 @@ public class AuroraApplication extends Application {
|
||||
return uninstaller;
|
||||
}
|
||||
|
||||
public static void rxNotify(Event event) {
|
||||
rxBus.getBus().accept(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
rxBus = new RxBus();
|
||||
installer = new Installer(this);
|
||||
uninstaller = new Uninstaller(this);
|
||||
|
||||
//Clear all old installation sessions.
|
||||
Util.clearOldInstallationSessions(this);
|
||||
|
||||
//Register global install broadcast receiver.
|
||||
registerReceiver(installer.getPackageInstaller().getBroadcastReceiver(),
|
||||
new IntentFilter(InstallerService.ACTION_INSTALLATION_STATUS_NOTIFICATION));
|
||||
RxJavaPlugins.setErrorHandler(err -> {
|
||||
});
|
||||
|
||||
//Global RX-Error handler, just simply logs, I make sure all errors are handled at origin.
|
||||
RxJavaPlugins.setErrorHandler(err -> Log.i(err.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
try {
|
||||
unregisterReceiver(installer.getPackageInstaller().getBroadcastReceiver());
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
super.onTerminate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import android.graphics.Bitmap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.GlideBuilder;
|
||||
import com.bumptech.glide.Registry;
|
||||
|
||||
110
app/src/main/java/com/aurora/store/BulkUpdateService.java
Normal file
110
app/src/main/java/com/aurora/store/BulkUpdateService.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package com.aurora.store;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.aurora.store.events.Event;
|
||||
import com.aurora.store.exception.CredentialsEmptyException;
|
||||
import com.aurora.store.exception.MalformedRequestException;
|
||||
import com.aurora.store.exception.NotPurchasedException;
|
||||
import com.aurora.store.exception.TooManyRequestsException;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.notification.QuickNotification;
|
||||
import com.aurora.store.task.LiveUpdate;
|
||||
import com.aurora.store.task.ObservableDeliveryData;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.dragons.aurora.playstoreapiv2.AuthException;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class BulkUpdateService extends Service {
|
||||
public static BulkUpdateService instance = null;
|
||||
|
||||
private List<App> appList = new ArrayList<>();
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
public static boolean isServiceRunning() {
|
||||
try {
|
||||
return instance != null && instance.isRunning();
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRunning() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
instance = this;
|
||||
appList = AuroraApplication.getOngoingUpdateList();
|
||||
updateAllApps();
|
||||
}
|
||||
|
||||
private void updateAllApps() {
|
||||
AuroraApplication.setBulkUpdateAlive(true);
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.BULK_UPDATE_NOTIFY));
|
||||
disposable.add(Observable.fromIterable(appList)
|
||||
.flatMap(app -> new ObservableDeliveryData(getApplicationContext()).getDeliveryData(app))
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext(deliveryDataBundle -> new LiveUpdate(getApplicationContext())
|
||||
.enqueueUpdate(deliveryDataBundle.getApp(),
|
||||
deliveryDataBundle.getAndroidAppDeliveryData()))
|
||||
.subscribe(deliveryDataBundle -> {
|
||||
}, err -> {
|
||||
if (err instanceof MalformedRequestException || err instanceof NotPurchasedException) {
|
||||
QuickNotification.show(getApplication(),
|
||||
getString(R.string.action_updates),
|
||||
err.getMessage(),
|
||||
null);
|
||||
}
|
||||
processException(err);
|
||||
Log.e(err.getMessage());
|
||||
}));
|
||||
}
|
||||
|
||||
private void processException(Throwable e) {
|
||||
if (e instanceof CredentialsEmptyException) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_ERROR));
|
||||
} else if (e instanceof AuthException | e instanceof TooManyRequestsException) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_FAILED));
|
||||
} else if (e instanceof UnknownHostException) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.NETWORK_UNAVAILABLE));
|
||||
} else
|
||||
Log.e(e.getMessage());
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
AuroraApplication.setBulkUpdateAlive(false);
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.BULK_UPDATE_NOTIFY));
|
||||
instance = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ public class Constants {
|
||||
public static final String INTENT_DEVICE_NAME = "INTENT_DEVICE_NAME";
|
||||
public static final String INTENT_DEVICE_INDEX = "INTENT_DEVICE_INDEX";
|
||||
public static final String INTENT_FRAGMENT_POSITION = "INTENT_FRAGMENT_POSITION";
|
||||
public static final String INTENT_PACKAGE_NAME = "INTENT_PACKAGE_NAME";
|
||||
|
||||
public static final String BUILD_DEVICE = "Build.DEVICE";
|
||||
public static final String BUILD_MANUFACTURER = "Build.MANUFACTURER";
|
||||
@@ -40,16 +41,18 @@ public class Constants {
|
||||
public static final String TAG = "Aurora Store";
|
||||
public static final String FILES = "Files";
|
||||
|
||||
public static final String CATEGORY_APPS = "APPLICATION";
|
||||
public static final String CATEGORY_GAME = "GAME";
|
||||
public static final String CATEGORY_FAMILY = "FAMILY";
|
||||
|
||||
public static final String TOP_APPS = "TOP_APPS";
|
||||
public static final String TOP_GAME = "TOP_GAME";
|
||||
public static final String TOP_FAMILY = "TOP_FAMILY";
|
||||
|
||||
public static final String RECENT_HISTORY = "RECENT_HISTORY";
|
||||
|
||||
public static final String FILTER_SYSTEM_APPS = "FILTER_SYSTEM_APPS";
|
||||
public static final String FILTER_APPS_WITH_ADS = "FILTER_APPS_WITH_ADS";
|
||||
public static final String FILTER_PAID_APPS = "FILTER_PAID_APPS";
|
||||
public static final String FILTER_GSF_DEPENDENT_APPS = "FILTER_GSF_DEPENDENT_APPS";
|
||||
public static final String FILTER_CATEGORY = "FILTER_CATEGORY";
|
||||
public static final String FILTER_RATING = "FILTER_RATING";
|
||||
public static final String FILTER_DOWNLOADS = "FILTER_DOWNLOADS";
|
||||
|
||||
public static final String NOTIFICATION_CHANNEL_ALERT = "NOTIFICATION_CHANNEL_ALERT";
|
||||
public static final String NOTIFICATION_CHANNEL_GENERAL = "NOTIFICATION_CHANNEL_GENERAL";
|
||||
|
||||
public static final String PRIVILEGED_EXTENSION_PACKAGE_NAME = "com.aurora.services";
|
||||
public static final String PRIVILEGED_EXTENSION_SERVICE_INTENT = "com.aurora.services.IPrivilegedService";
|
||||
@@ -57,9 +60,7 @@ public class Constants {
|
||||
public static final String PREFERENCE_THEME = "PREFERENCE_THEME";
|
||||
public static final String PREFERENCE_DEFAULT_TAB = "PREFERENCE_DEFAULT_TAB";
|
||||
public static final String PREFERENCE_UI_CARD_STYLE = "PREFERENCE_UI_CARD_STYLE";
|
||||
public static final String PREFERENCE_UI_TRANSPARENT = "PREFERENCE_UI_TRANSPARENT";
|
||||
public static final String PREFERENCE_FEATURED_SNAP = "PREFERENCE_FEATURED_SNAP";
|
||||
public static final String PREFERENCE_TAB_MODE = "PREFERENCE_TAB_MODE";
|
||||
public static final String PREFERENCE_SEARCH_IME = "PREFERENCE_SEARCH_IME";
|
||||
public static final String PREFERENCE_SEARCH_PACKAGE = "PREFERENCE_SEARCH_PACKAGE";
|
||||
public static final String PREFERENCE_DO_NOT_SHOW_INTRO = "PREFERENCE_DO_NOT_SHOW_INTRO";
|
||||
@@ -70,6 +71,7 @@ public class Constants {
|
||||
public static final String PREFERENCE_DEVICE_TO_PRETEND_TO_BE_INDEX = "PREFERENCE_DEVICE_TO_PRETEND_TO_BE_INDEX";
|
||||
public static final String PREFERENCE_REQUESTED_LOCATION_INDEX = "PREFERENCE_REQUESTED_LOCATION_INDEX";
|
||||
public static final String PREFERENCE_BLACKLIST_APPS_LIST = "PREFERENCE_BLACKLIST_APPS_LIST";
|
||||
public static final String PREFERENCE_FILTER_APPS = "PREFERENCE_FILTER_APPS";
|
||||
public static final String PREFERENCE_FILTER_GOOGLE = "PREFERENCE_FILTER_GOOGLE";
|
||||
public static final String PREFERENCE_FILTER_F_DROID = "PREFERENCE_FILTER_F_DROID";
|
||||
public static final String PREFERENCE_FILTER_SEARCH = "PREFERENCE_FILTER_SEARCH";
|
||||
@@ -109,11 +111,16 @@ public class Constants {
|
||||
public static final String PREFERENCE_INSTALLATION_PROFILE = "PREFERENCE_INSTALLATION_PROFILE";
|
||||
public static final String PREFERENCE_ACCOUNTS_PASSWORD_SWITCH = "PREFERENCE_ACCOUNTS_PASSWORD_SWITCH";
|
||||
|
||||
public static final String PREFERENCE_TOP_APPS = "PREFERENCE_TOP_APPS";
|
||||
public static final String PREFERENCE_TOP_GAMES = "PREFERENCE_TOP_GAMES";
|
||||
public static final String PREFERENCE_TOP_FAMILY = "PREFERENCE_TOP_FAMILY";
|
||||
public static final String PREFERENCE_INSTALLED_APPS = "PREFERENCE_INSTALLED_APPS";
|
||||
public static final String PREFERENCE_CACHE_DATE = "PREFERENCE_CACHE_DATE";
|
||||
public static final String PREFERENCE_SELF_UPDATE_DATE = "PREFERENCE_SELF_UPDATE_DATE";
|
||||
public static final String PREFERENCE_SELF_UPDATE = "PREFERENCE_SELF_UPDATE";
|
||||
|
||||
|
||||
public static final String FRAGMENT_NAME = "FRAGMENT_NAME";
|
||||
public static final String FRAGMENT_ABOUT = "FRAGMENT_ABOUT";
|
||||
public static final String FRAGMENT_ACCOUNTS = "FRAGMENT_ACCOUNTS";
|
||||
public static final String FRAGMENT_BLACKLIST = "FRAGMENT_BLACKLIST";
|
||||
public static final String FRAGMENT_FAV_LIST = "FRAGMENT_FAV_LIST";
|
||||
public static final String FRAGMENT_SPOOF = "FRAGMENT_SPOOF";
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.adapter.SelectableViewHolder;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FavouriteItemTouchHelper extends ItemTouchHelper.SimpleCallback {
|
||||
|
||||
private RecyclerItemTouchHelperListener listener;
|
||||
|
||||
public FavouriteItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
|
||||
super(dragDirs, swipeDirs);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder, @NotNull RecyclerView.ViewHolder target) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
|
||||
if (viewHolder != null) {
|
||||
final View foregroundView = ((SelectableViewHolder) viewHolder).viewForeground;
|
||||
getDefaultUIUtil().onSelected(foregroundView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildDrawOver(@NotNull Canvas c, @NotNull RecyclerView recyclerView,
|
||||
RecyclerView.ViewHolder viewHolder, float dX, float dY,
|
||||
int actionState, boolean isCurrentlyActive) {
|
||||
final View foregroundView = ((SelectableViewHolder) viewHolder).viewForeground;
|
||||
getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
|
||||
actionState, isCurrentlyActive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder) {
|
||||
final View foregroundView = ((SelectableViewHolder) viewHolder).viewForeground;
|
||||
getDefaultUIUtil().clearView(foregroundView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildDraw(@NotNull Canvas c, @NotNull RecyclerView recyclerView, @NotNull
|
||||
RecyclerView.ViewHolder viewHolder, float dX, float dY,
|
||||
int actionState, boolean isCurrentlyActive) {
|
||||
final View foregroundView = ((SelectableViewHolder) viewHolder).viewForeground;
|
||||
|
||||
getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
|
||||
actionState, isCurrentlyActive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(@NotNull RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
|
||||
return super.convertToAbsoluteDirection(flags, layoutDirection);
|
||||
}
|
||||
|
||||
public interface RecyclerItemTouchHelperListener {
|
||||
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Yalp Store
|
||||
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
|
||||
public class Filter {
|
||||
|
||||
private Context context;
|
||||
|
||||
public Filter(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public com.aurora.store.model.Filter getFilterPreferences() {
|
||||
com.aurora.store.model.Filter filter = new com.aurora.store.model.Filter();
|
||||
SharedPreferences prefs = Util.getPrefs(context);
|
||||
filter.setSystemApps(prefs.getBoolean(Constants.FILTER_SYSTEM_APPS, false));
|
||||
filter.setAppsWithAds(prefs.getBoolean(Constants.FILTER_APPS_WITH_ADS, true));
|
||||
filter.setPaidApps(prefs.getBoolean(Constants.FILTER_PAID_APPS, true));
|
||||
filter.setGsfDependentApps(prefs.getBoolean(Constants.FILTER_GSF_DEPENDENT_APPS, true));
|
||||
filter.setCategory(prefs.getString(Constants.FILTER_CATEGORY, Constants.TOP));
|
||||
filter.setRating(prefs.getFloat(Constants.FILTER_RATING, 0.0f));
|
||||
filter.setDownloads(prefs.getInt(Constants.FILTER_DOWNLOADS, 0));
|
||||
return filter;
|
||||
}
|
||||
|
||||
public void resetFilterPreferences() {
|
||||
SharedPreferences prefs = Util.getPrefs(context);
|
||||
PrefUtil.putBoolean(context, Constants.FILTER_SYSTEM_APPS, false);
|
||||
PrefUtil.putBoolean(context, Constants.FILTER_APPS_WITH_ADS, true);
|
||||
PrefUtil.putBoolean(context, Constants.FILTER_PAID_APPS, true);
|
||||
PrefUtil.putBoolean(context, Constants.FILTER_GSF_DEPENDENT_APPS, true);
|
||||
PrefUtil.putString(context, Constants.FILTER_CATEGORY, Constants.TOP);
|
||||
PrefUtil.putFloat(context, Constants.FILTER_RATING, 0.0f);
|
||||
PrefUtil.putInteger(context, Constants.FILTER_DOWNLOADS, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.adapter.SearchHistoryAdapter;
|
||||
|
||||
public class HistoryItemTouchHelper extends ItemTouchHelper.SimpleCallback {
|
||||
|
||||
private RecyclerItemTouchHelperListener listener;
|
||||
|
||||
public HistoryItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
|
||||
super(dragDirs, swipeDirs);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
|
||||
if (viewHolder != null) {
|
||||
final View foregroundView = ((SearchHistoryAdapter.ViewHolder) viewHolder).viewForeground;
|
||||
getDefaultUIUtil().onSelected(foregroundView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
|
||||
RecyclerView.ViewHolder viewHolder, float dX, float dY,
|
||||
int actionState, boolean isCurrentlyActive) {
|
||||
final View foregroundView = ((SearchHistoryAdapter.ViewHolder) viewHolder).viewForeground;
|
||||
getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
|
||||
actionState, isCurrentlyActive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||
final View foregroundView = ((SearchHistoryAdapter.ViewHolder) viewHolder).viewForeground;
|
||||
getDefaultUIUtil().clearView(foregroundView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildDraw(Canvas c, RecyclerView recyclerView,
|
||||
RecyclerView.ViewHolder viewHolder, float dX, float dY,
|
||||
int actionState, boolean isCurrentlyActive) {
|
||||
final View foregroundView = ((SearchHistoryAdapter.ViewHolder) viewHolder).viewForeground;
|
||||
|
||||
getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
|
||||
actionState, isCurrentlyActive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
|
||||
return super.convertToAbsoluteDirection(flags, layoutDirection);
|
||||
}
|
||||
|
||||
public interface RecyclerItemTouchHelperListener {
|
||||
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
|
||||
public enum ListType {
|
||||
INSTALLED,
|
||||
UPDATES,
|
||||
ENDLESS
|
||||
}
|
||||
@@ -37,8 +37,8 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.aurora.store.util.ViewUtil;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -101,7 +101,7 @@ public class PermissionGroup extends LinearLayout {
|
||||
|
||||
public void setPermissionGroupInfo(final PermissionGroupInfo permissionGroupInfo) {
|
||||
this.permissionGroupInfo = permissionGroupInfo;
|
||||
ImageView imageView = (ImageView) findViewById(R.id.permission_group_icon);
|
||||
ImageView imageView = findViewById(R.id.permission_group_icon);
|
||||
imageView.setImageDrawable(getPermissionGroupIcon(permissionGroupInfo));
|
||||
imageView.setColorFilter(ViewUtil.getStyledAttribute(imageView.getContext(), android.R.attr.colorAccent));
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Yalp Store
|
||||
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class PermissionsComparator {
|
||||
|
||||
private Context context;
|
||||
|
||||
public PermissionsComparator(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public boolean isSame(App app) {
|
||||
Log.i("Checking %s", app.getPackageName());
|
||||
Set<String> oldPermissions = getOldPermissions(app.getPackageName());
|
||||
if (null == oldPermissions) {
|
||||
return true;
|
||||
}
|
||||
Set<String> newPermissions = new HashSet<>(app.getPermissions());
|
||||
newPermissions.removeAll(oldPermissions);
|
||||
Log.i(newPermissions.isEmpty()
|
||||
? app.getPackageName() + " requests no new permissions"
|
||||
: app.getPackageName() + " requests new permissions: " + TextUtils.join(", ", newPermissions));
|
||||
return newPermissions.isEmpty();
|
||||
}
|
||||
|
||||
private Set<String> getOldPermissions(String packageName) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
try {
|
||||
PackageInfo pi = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
|
||||
return new HashSet<>(Arrays.asList(
|
||||
null == pi.requestedPermissions
|
||||
? new String[0]
|
||||
: pi.requestedPermissions
|
||||
));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e("Package " + packageName + " doesn't seem to be installed");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
37
app/src/main/java/com/aurora/store/ReviewsDiffCallback.java
Normal file
37
app/src/main/java/com/aurora/store/ReviewsDiffCallback.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.aurora.store;
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
import com.aurora.store.model.Review;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ReviewsDiffCallback extends DiffUtil.Callback {
|
||||
private List<Review> newList;
|
||||
private List<Review> oldList;
|
||||
|
||||
public ReviewsDiffCallback(List<Review> newList, List<Review> oldList) {
|
||||
this.newList = newList;
|
||||
this.oldList = oldList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOldListSize() {
|
||||
return oldList != null ? oldList.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize() {
|
||||
return newList != null ? newList.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldIndex, int newIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldIndex, int newIndex) {
|
||||
return oldList.get(oldIndex).equals(newList.get(newIndex));
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,10 @@ import com.aurora.store.download.RequestBuilder;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.model.Update;
|
||||
import com.aurora.store.task.NetworkTask;
|
||||
import com.aurora.store.utility.CertUtil;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
import com.aurora.store.util.CertUtil;
|
||||
import com.aurora.store.util.ContextUtil;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.PackageUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.tonyodev.fetch2.AbstractFetchGroupListener;
|
||||
import com.tonyodev.fetch2.Download;
|
||||
@@ -79,6 +79,7 @@ public class SelfUpdateService extends Service {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
instance = this;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
startForeground(1, getNotification());
|
||||
} else {
|
||||
@@ -119,7 +120,7 @@ public class SelfUpdateService extends Service {
|
||||
} else
|
||||
downloadAndUpdate(update);
|
||||
} catch (Exception e) {
|
||||
Log.e("Error checking self-update");
|
||||
Log.d("Error checking self-update");
|
||||
destroyService();
|
||||
}
|
||||
}));
|
||||
@@ -189,7 +190,7 @@ public class SelfUpdateService extends Service {
|
||||
public void onError(int groupId, @NotNull Download download, @NotNull Error error,
|
||||
@org.jetbrains.annotations.Nullable Throwable throwable, @NotNull FetchGroup fetchGroup) {
|
||||
if (groupId == hashCode) {
|
||||
Log.e("Error self-updating %s", app.getDisplayName());
|
||||
Log.d("Error self-updating %s", app.getDisplayName());
|
||||
destroyService();
|
||||
}
|
||||
}
|
||||
@@ -205,7 +206,7 @@ public class SelfUpdateService extends Service {
|
||||
@Override
|
||||
public void onCancelled(int groupId, @NotNull Download download, @NotNull FetchGroup fetchGroup) {
|
||||
if (groupId == hashCode) {
|
||||
Log.e("Self-update cancelled %s", app.getDisplayName());
|
||||
Log.d("Self-update cancelled %s", app.getDisplayName());
|
||||
destroyService();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.aurora.store;
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
import com.dragons.aurora.playstoreapiv2.SearchSuggestEntry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SuggestionDiffCallback extends DiffUtil.Callback {
|
||||
private List<SearchSuggestEntry> newList;
|
||||
private List<SearchSuggestEntry> oldList;
|
||||
|
||||
public SuggestionDiffCallback(List<SearchSuggestEntry> newList, List<SearchSuggestEntry> oldList) {
|
||||
this.newList = newList;
|
||||
this.oldList = oldList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOldListSize() {
|
||||
return oldList != null ? oldList.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize() {
|
||||
return newList != null ? newList.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldIndex, int newIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldIndex, int newIndex) {
|
||||
return oldList.get(oldIndex).equals(newList.get(newIndex));
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,8 @@ package com.aurora.store;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
130
app/src/main/java/com/aurora/store/ValidateApiService.java
Normal file
130
app/src/main/java/com/aurora/store/ValidateApiService.java
Normal file
@@ -0,0 +1,130 @@
|
||||
package com.aurora.store;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.events.Event;
|
||||
import com.aurora.store.exception.CredentialsEmptyException;
|
||||
import com.aurora.store.exception.TooManyRequestsException;
|
||||
import com.aurora.store.util.ApiBuilderUtil;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.dragons.aurora.playstoreapiv2.AuthException;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.TocResponse;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class ValidateApiService extends Service {
|
||||
public static ValidateApiService instance = null;
|
||||
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
|
||||
public static boolean isServiceRunning() {
|
||||
try {
|
||||
return instance != null && instance.isRunning();
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRunning() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
instance = this;
|
||||
buildAndTestApi();
|
||||
}
|
||||
|
||||
private void buildAndTestApi() {
|
||||
Log.d(getString(R.string.toast_api_build_api));
|
||||
disposable.clear();
|
||||
disposable.add(Observable.fromCallable(() -> new PlayStoreApiAuthenticator()
|
||||
.getPlayApi(this))
|
||||
.flatMap(api -> {
|
||||
AuroraApplication.api = api;
|
||||
return getTocResponse(api);
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> {
|
||||
Log.d(getString(R.string.toast_api_all_ok));
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_SUCCESS));
|
||||
}, err -> {
|
||||
Log.d(getString(R.string.toast_api_build_failed));
|
||||
processException(err);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private void processException(Throwable e) {
|
||||
if (e instanceof CredentialsEmptyException) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_ERROR));
|
||||
} else if (e instanceof AuthException | e instanceof TooManyRequestsException) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_FAILED));
|
||||
getNewAuthToken();
|
||||
} else if (e instanceof UnknownHostException) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.NETWORK_UNAVAILABLE));
|
||||
} else
|
||||
Log.e(e.getMessage());
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
public void getNewAuthToken() {
|
||||
disposable.clear();
|
||||
disposable.add(Observable.fromCallable(() -> ApiBuilderUtil
|
||||
.generateApiWithNewAuthToken(this))
|
||||
.flatMap(api -> {
|
||||
AuroraApplication.api = api;
|
||||
return getTocResponse(api);
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_SUCCESS));
|
||||
}, err -> {
|
||||
Log.e(err.getMessage());
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.API_ERROR));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public Observable<TocResponse> getTocResponse(GooglePlayAPI api) {
|
||||
return Observable.create(emitter -> {
|
||||
TocResponse tocResponse = api.toc();
|
||||
emitter.onNext(tocResponse);
|
||||
emitter.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
instance = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -1,321 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.aurora.store.BuildConfig;
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.SelfUpdateService;
|
||||
import com.aurora.store.adapter.ViewPagerAdapter;
|
||||
import com.aurora.store.fragment.AppsFragment;
|
||||
import com.aurora.store.fragment.HomeFragment;
|
||||
import com.aurora.store.fragment.SearchFragment;
|
||||
import com.aurora.store.model.Update;
|
||||
import com.aurora.store.task.NetworkTask;
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.CertUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.NetworkUtil;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.TextUtil;
|
||||
import com.aurora.store.utility.ThemeUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.aurora.store.view.CustomViewPager;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class AuroraActivity extends AppCompatActivity {
|
||||
|
||||
|
||||
public static String externalQuery;
|
||||
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
@BindView(R.id.viewpager)
|
||||
CustomViewPager viewPager;
|
||||
@BindView(R.id.bottom_navigation)
|
||||
BottomNavigationView bottomNavigationView;
|
||||
|
||||
private ActionBar actionBar;
|
||||
private ViewPagerAdapter pagerAdapter;
|
||||
private ThemeUtil themeUtil = new ThemeUtil();
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
private int fragmentCur = 0;
|
||||
private boolean isSearchIntent = false;
|
||||
|
||||
public BottomNavigationView getBottomNavigation() {
|
||||
return bottomNavigationView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
themeUtil.onCreate(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
ButterKnife.bind(this);
|
||||
fragmentCur = Util.getDefaultTab(this);
|
||||
onNewIntent(getIntent());
|
||||
|
||||
if (!PrefUtil.getBoolean(this, Constants.PREFERENCE_DO_NOT_SHOW_INTRO)) {
|
||||
PrefUtil.putBoolean(this, Constants.PREFERENCE_DO_NOT_SHOW_INTRO, true);
|
||||
startActivity(new Intent(this, IntroActivity.class));
|
||||
finish();
|
||||
} else {
|
||||
if (Accountant.isLoggedIn(this))
|
||||
init();
|
||||
else
|
||||
startActivity(new Intent(this, AccountsActivity.class));
|
||||
}
|
||||
|
||||
if (NetworkUtil.isConnected(this)) {
|
||||
if (Util.isCacheObsolete(this))
|
||||
Util.clearCache(this);
|
||||
|
||||
if (Util.shouldCheckUpdate(this) && !SelfUpdateService.isServiceRunning())
|
||||
checkSelfUpdate();
|
||||
}
|
||||
checkPermissions();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setupActionbar();
|
||||
setupViewPager();
|
||||
setupBottomNavigation();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
Bundle bundle = intent.getExtras();
|
||||
if (bundle != null)
|
||||
fragmentCur = bundle.getInt(Constants.INTENT_FRAGMENT_POSITION);
|
||||
else if (intent.getScheme() != null && intent.getScheme().equals("market")) {
|
||||
fragmentCur = 2;
|
||||
isSearchIntent = true;
|
||||
if (intent.getData() != null)
|
||||
externalQuery = intent.getData().getQueryParameter("q");
|
||||
} else
|
||||
fragmentCur = Util.getDefaultTab(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Fragment fragment = pagerAdapter.getItem(viewPager.getCurrentItem());
|
||||
if (!fragment.isAdded())
|
||||
return;
|
||||
if (fragment instanceof SearchFragment || fragment instanceof HomeFragment) {
|
||||
FragmentManager fragmentManager = fragment.getChildFragmentManager();
|
||||
if (!fragmentManager.getFragments().isEmpty())
|
||||
fragmentManager.popBackStack();
|
||||
else
|
||||
super.onBackPressed();
|
||||
} else
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
return super.onSupportNavigateUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
case R.id.action_download:
|
||||
startActivity(new Intent(this, DownloadsActivity.class));
|
||||
return true;
|
||||
case R.id.action_setting:
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(menuItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
themeUtil.onResume(this);
|
||||
Util.toggleSoftInput(this, false);
|
||||
if (pagerAdapter == null)
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUserLeaveHint() {
|
||||
super.onUserLeaveHint();
|
||||
Util.toggleSoftInput(this, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
disposable.clear();
|
||||
}
|
||||
|
||||
private void setupActionbar() {
|
||||
setSupportActionBar(toolbar);
|
||||
actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowCustomEnabled(true);
|
||||
actionBar.setElevation(0f);
|
||||
actionBar.setTitle(getString(R.string.app_name));
|
||||
}
|
||||
}
|
||||
|
||||
private void setupViewPager() {
|
||||
pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
|
||||
pagerAdapter.addFragment(0, new HomeFragment());
|
||||
pagerAdapter.addFragment(1, new AppsFragment());
|
||||
pagerAdapter.addFragment(2, new SearchFragment());
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
viewPager.setScroll(false);
|
||||
viewPager.setOffscreenPageLimit(2);
|
||||
viewPager.setCurrentItem(fragmentCur, true);
|
||||
}
|
||||
|
||||
private void setupBottomNavigation() {
|
||||
@ColorInt
|
||||
int backGroundColor = ViewUtil.getStyledAttribute(this, android.R.attr.colorBackground);
|
||||
bottomNavigationView.setBackgroundColor(ColorUtils.setAlphaComponent(backGroundColor, 245));
|
||||
bottomNavigationView.setOnNavigationItemSelectedListener(menuItem -> {
|
||||
viewPager.setCurrentItem(menuItem.getOrder(), true);
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_home:
|
||||
Util.toggleSoftInput(this, false);
|
||||
actionBar.setTitle(getString(R.string.title_home));
|
||||
break;
|
||||
case R.id.action_apps:
|
||||
Util.toggleSoftInput(this, false);
|
||||
actionBar.setTitle(getString(R.string.title_installed));
|
||||
break;
|
||||
case R.id.action_search:
|
||||
if (Util.isIMEEnabled(this))
|
||||
Util.toggleSoftInput(this, true);
|
||||
actionBar.setTitle(getString(R.string.title_search));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (isSearchIntent)
|
||||
bottomNavigationView.setSelectedItemId(R.id.action_search);
|
||||
if (fragmentCur != 0 && !isSearchIntent)
|
||||
bottomNavigationView.setSelectedItemId(bottomNavigationView.getMenu()
|
||||
.getItem(fragmentCur).getItemId());
|
||||
}
|
||||
|
||||
private void checkSelfUpdate() {
|
||||
disposable.add(Observable.fromCallable(() -> new NetworkTask(this)
|
||||
.get(Constants.UPDATE_URL))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> {
|
||||
try {
|
||||
Util.setSelfUpdateTime(this, Calendar.getInstance().getTimeInMillis());
|
||||
Gson gson = new Gson();
|
||||
Update update = gson.fromJson(response, Update.class);
|
||||
if (update.getVersionCode() > BuildConfig.VERSION_CODE) {
|
||||
if (CertUtil.isFDroidApp(this, BuildConfig.APPLICATION_ID)
|
||||
&& TextUtil.emptyIfNull(update.getFdroidBuild()).isEmpty()) {
|
||||
Log.d("FDroid build of latest version is not published yet");
|
||||
return;
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
showAddRepoDialog(update);
|
||||
} else {
|
||||
Log.i("No new update available");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("Error checking updates");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void checkPermissions() {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||
1337);
|
||||
}
|
||||
}
|
||||
|
||||
protected void showAddRepoDialog(Update update) {
|
||||
final String changelog = TextUtil.emptyIfNull(update.getChangelog());
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.dialog_title_self_update))
|
||||
.setMessage(new StringBuilder()
|
||||
.append(update.getVersionName())
|
||||
.append("\n\n")
|
||||
.append(changelog.isEmpty() ? getString(R.string.details_no_changes) : changelog)
|
||||
.append("\n\n")
|
||||
.append(getString(R.string.dialog_desc_self_update))
|
||||
.toString())
|
||||
.setPositiveButton(getString(android.R.string.yes), (dialog, which) -> {
|
||||
Intent intent = new Intent(this, SelfUpdateService.class);
|
||||
startService(intent);
|
||||
})
|
||||
.setNegativeButton(getString(android.R.string.no), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.activity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.fragment.DetailsFragment;
|
||||
import com.aurora.store.manager.BlacklistManager;
|
||||
import com.aurora.store.manager.FavouriteListManager;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.ThemeUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class DetailsActivity extends AppCompatActivity {
|
||||
|
||||
public static final String INTENT_PACKAGE_NAME = "INTENT_PACKAGE_NAME";
|
||||
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
|
||||
private String packageName;
|
||||
private DetailsFragment detailsFragment;
|
||||
private ThemeUtil themeUtil = new ThemeUtil();
|
||||
private FavouriteListManager favouriteListManager;
|
||||
|
||||
static public Intent getDetailsIntent(Context context, String packageName) {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra(DetailsActivity.INTENT_PACKAGE_NAME, packageName);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
themeUtil.onCreate(this);
|
||||
setContentView(R.layout.activity_details);
|
||||
ButterKnife.bind(this);
|
||||
setupActionBar();
|
||||
favouriteListManager = new FavouriteListManager(this);
|
||||
onNewIntent(getIntent());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
|
||||
packageName = getIntentPackageName(intent);
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
Log.e("No package name provided");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
Log.i("Getting info about %s", packageName);
|
||||
grabDetails(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_app_details, menu);
|
||||
menu.findItem(R.id.action_favourite).setIcon(favouriteListManager.contains(packageName)
|
||||
? R.drawable.ic_favourite_red
|
||||
: R.drawable.ic_favourite_remove);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
case R.id.action_favourite:
|
||||
if (favouriteListManager.contains(packageName)) {
|
||||
favouriteListManager.remove(packageName);
|
||||
menuItem.setIcon(R.drawable.ic_favourite_remove);
|
||||
} else {
|
||||
favouriteListManager.add(packageName);
|
||||
menuItem.setIcon(R.drawable.ic_favourite_red);
|
||||
}
|
||||
return true;
|
||||
case R.id.action_manual:
|
||||
startActivity(new Intent(this, ManualDownloadActivity.class));
|
||||
return true;
|
||||
case R.id.action_downloads:
|
||||
startActivity(new Intent(this, DownloadsActivity.class));
|
||||
return true;
|
||||
case R.id.action_blacklist:
|
||||
new BlacklistManager(this).add(packageName);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(menuItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
themeUtil.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
List<Fragment> fragments = getSupportFragmentManager().getFragments();
|
||||
if (fragments.get(0) instanceof DetailsFragment) {
|
||||
FragmentManager fm = fragments.get(0).getChildFragmentManager();
|
||||
if (!fm.getFragments().isEmpty())
|
||||
fm.popBackStack();
|
||||
else
|
||||
super.onBackPressed();
|
||||
} else
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
private void setupActionBar() {
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar mActionBar = getSupportActionBar();
|
||||
if (mActionBar != null) {
|
||||
mActionBar.setDisplayHomeAsUpEnabled(true);
|
||||
mActionBar.setDisplayShowTitleEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private String getIntentPackageName(Intent intent) {
|
||||
if (intent.hasExtra(INTENT_PACKAGE_NAME)) {
|
||||
return intent.getStringExtra(INTENT_PACKAGE_NAME);
|
||||
} else if (intent.getScheme() != null
|
||||
&& (intent.getScheme().equals("market")
|
||||
|| intent.getScheme().equals("http")
|
||||
|| intent.getScheme().equals("https"))) {
|
||||
return intent.getData().getQueryParameter("id");
|
||||
} else if (intent.getExtras() != null) {
|
||||
Bundle bundle = intent.getExtras();
|
||||
return bundle.getString(INTENT_PACKAGE_NAME);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void grabDetails(String packageName) {
|
||||
detailsFragment = new DetailsFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("PackageName", packageName);
|
||||
detailsFragment.setArguments(arguments);
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.content, detailsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.commitAllowingStateLoss();
|
||||
}
|
||||
|
||||
public void redrawButtons() {
|
||||
if (detailsFragment != null)
|
||||
detailsFragment.drawButtons();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.adapter.ViewPagerAdapter;
|
||||
import com.aurora.store.fragment.AccountsFragment;
|
||||
import com.aurora.store.fragment.intro.LoginFragment;
|
||||
import com.aurora.store.fragment.intro.PermissionFragment;
|
||||
import com.aurora.store.fragment.intro.WelcomeFragment;
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.ThemeUtil;
|
||||
import com.aurora.store.view.CustomViewPager;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class IntroActivity extends AppCompatActivity {
|
||||
|
||||
@BindView(R.id.viewpager)
|
||||
CustomViewPager viewPager;
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
|
||||
private ActionBar actionBar;
|
||||
private ThemeUtil themeUtil = new ThemeUtil();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
themeUtil.onCreate(this);
|
||||
setContentView(R.layout.activity_intro);
|
||||
ButterKnife.bind(this);
|
||||
setupActionbar();
|
||||
setupViewPager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_intro, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_setting:
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(menuItem);
|
||||
}
|
||||
|
||||
private void setupActionbar() {
|
||||
setSupportActionBar(toolbar);
|
||||
actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowCustomEnabled(true);
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setElevation(0f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
themeUtil.onResume(this);
|
||||
if (Accountant.isLoggedIn(this)) {
|
||||
startActivity(new Intent(this, AuroraActivity.class));
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void setupViewPager() {
|
||||
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
|
||||
viewPagerAdapter.addFragment(0, new WelcomeFragment());
|
||||
viewPagerAdapter.addFragment(1, new PermissionFragment());
|
||||
viewPagerAdapter.addFragment(2, new LoginFragment());
|
||||
viewPager.setAdapter(viewPagerAdapter);
|
||||
viewPager.setScroll(false);
|
||||
}
|
||||
|
||||
public void moveForward() {
|
||||
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.model.App;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
|
||||
public class BlacklistAdapter extends SelectableAdapter<BlacklistAdapter.ViewHolder> {
|
||||
|
||||
private List<App> appList;
|
||||
private ItemClickListener itemClickListener;
|
||||
|
||||
public BlacklistAdapter(Context context, List<App> appList, ItemClickListener itemClickListener) {
|
||||
super(context);
|
||||
this.itemClickListener = itemClickListener;
|
||||
this.appList = appList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
|
||||
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_blacklist, parent, false);
|
||||
return new ViewHolder(itemLayoutView, itemClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NotNull ViewHolder viewHolder, int position) {
|
||||
final App app = appList.get(position);
|
||||
viewHolder.label.setText(app.getDisplayName());
|
||||
viewHolder.packageName.setText(app.getPackageName());
|
||||
viewHolder.checkBox.setChecked(isSelected(app.getPackageName()));
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(app.getIconInfo().getUrl())
|
||||
.into(viewHolder.icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleSelection(int position) {
|
||||
String packageName = appList.get(position).getPackageName();
|
||||
if (mSelections.contains(packageName)) {
|
||||
mSelections.remove(packageName);
|
||||
mBlacklistManager.remove(packageName);
|
||||
} else {
|
||||
mSelections.add(packageName);
|
||||
}
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
public int getSelectedCount() {
|
||||
return mSelections.size();
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClicked(int position);
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.label)
|
||||
TextView label;
|
||||
@BindView(R.id.packageName)
|
||||
TextView packageName;
|
||||
@BindView(R.id.icon)
|
||||
ImageView icon;
|
||||
@BindView(R.id.check)
|
||||
CheckBox checkBox;
|
||||
|
||||
private ItemClickListener listener;
|
||||
|
||||
ViewHolder(View itemLayoutView, ItemClickListener listener) {
|
||||
super(itemLayoutView);
|
||||
this.listener = listener;
|
||||
ButterKnife.bind(this, itemView);
|
||||
itemLayoutView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.onItemClicked(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.SharedPreferencesTranslator;
|
||||
import com.aurora.store.fragment.CategoryAppsFragment;
|
||||
import com.aurora.store.utility.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class CategoriesListAdapter extends RecyclerView.Adapter<CategoriesListAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private Fragment fragment;
|
||||
private Map<String, String> categories = new HashMap<>();
|
||||
|
||||
private Integer[] categoriesImg = {
|
||||
R.drawable.ic_android_wear,
|
||||
R.drawable.ic_art_design,
|
||||
R.drawable.ic_auto_vehicles,
|
||||
R.drawable.ic_beauty,
|
||||
R.drawable.ic_books_reference,
|
||||
R.drawable.ic_business,
|
||||
R.drawable.ic_comics,
|
||||
R.drawable.ic_communication,
|
||||
R.drawable.ic_dating,
|
||||
R.drawable.ic_education,
|
||||
R.drawable.ic_entertainment,
|
||||
R.drawable.ic_events,
|
||||
R.drawable.ic_family,
|
||||
R.drawable.ic_finance,
|
||||
R.drawable.ic_food_drink,
|
||||
R.drawable.ic_games,
|
||||
R.drawable.ic_health_fitness,
|
||||
R.drawable.ic_house_home,
|
||||
R.drawable.ic_libraries_demo,
|
||||
R.drawable.ic_lifestyle,
|
||||
R.drawable.ic_maps_navigation,
|
||||
R.drawable.ic_medical,
|
||||
R.drawable.ic_music__audio,
|
||||
R.drawable.ic_news_magazines,
|
||||
R.drawable.ic_parenting,
|
||||
R.drawable.ic_personalization,
|
||||
R.drawable.ic_photography,
|
||||
R.drawable.ic_productivity,
|
||||
R.drawable.ic_shopping,
|
||||
R.drawable.ic_social,
|
||||
R.drawable.ic_sports,
|
||||
R.drawable.ic_tools,
|
||||
R.drawable.ic_travel_local,
|
||||
R.drawable.ic_video_editors,
|
||||
R.drawable.ic_weather,
|
||||
};
|
||||
|
||||
private SharedPreferencesTranslator translator;
|
||||
|
||||
public CategoriesListAdapter(Fragment fragment) {
|
||||
this.fragment = fragment;
|
||||
this.context = fragment.getContext();
|
||||
translator = new SharedPreferencesTranslator(Util.getPrefs(context));
|
||||
}
|
||||
|
||||
public void addData(Map<String, String> categories) {
|
||||
this.categories.clear();
|
||||
this.categories = categories;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean isDataEmpty() {
|
||||
return categories.isEmpty();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_category_list, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
|
||||
holder.topLabel.setText(translator.getString(new ArrayList<>(categories.keySet()).get(position)));
|
||||
holder.topImage.setImageDrawable(context.getResources().getDrawable(categoriesImg[position]));
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
CategoryAppsFragment categoryAppsFragment = new CategoryAppsFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("CategoryId", new ArrayList<>(categories.keySet()).get(position));
|
||||
arguments.putString("CategoryName", translator.getString(new ArrayList<>(categories.keySet()).get(position)));
|
||||
categoryAppsFragment.setArguments(arguments);
|
||||
FragmentManager fragmentManager = fragment.getFragmentManager();
|
||||
if (fragmentManager != null)
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.coordinator, categoryAppsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return categories.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@BindView(R.id.all_cat_img)
|
||||
ImageView topImage;
|
||||
@BindView(R.id.all_cat_name)
|
||||
TextView topLabel;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,15 +30,20 @@ import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.activity.DownloadsActivity;
|
||||
import com.aurora.store.sheet.DownloadMenuSheet;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.ui.details.DetailsActivity;
|
||||
import com.aurora.store.ui.single.activity.DownloadsActivity;
|
||||
import com.aurora.store.util.PackageUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.aurora.store.util.ViewUtil;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.tonyodev.fetch2.Download;
|
||||
import com.tonyodev.fetch2.Status;
|
||||
|
||||
@@ -105,6 +110,7 @@ public class DownloadsAdapter extends RecyclerView.Adapter<DownloadsAdapter.View
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(iconURL)
|
||||
.transforms(new CenterCrop(), new RoundedCorners(30))
|
||||
.into(viewHolder.imgDownload);
|
||||
|
||||
viewHolder.txtTitle.setText(displayName);
|
||||
@@ -138,8 +144,8 @@ public class DownloadsAdapter extends RecyclerView.Adapter<DownloadsAdapter.View
|
||||
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra("INTENT_PACKAGE_NAME", packageName);
|
||||
context.startActivity(intent);
|
||||
intent.putExtra(Constants.INTENT_PACKAGE_NAME, packageName);
|
||||
context.startActivity(intent, ViewUtil.getEmptyActivityBundle((AppCompatActivity) context));
|
||||
});
|
||||
|
||||
viewHolder.itemView.setOnLongClickListener(v -> {
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.aurora.store.ListType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EndlessAppsAdapter extends InstalledAppsAdapter {
|
||||
|
||||
public EndlessAppsAdapter(Context context) {
|
||||
super(context, ListType.ENDLESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull InstalledAppsAdapter.ViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDetails(List<String> Version, List<String> Extra, App app) {
|
||||
Version.add(Util.addSiPrefix(app.getSize()));
|
||||
if (!app.isEarlyAccess())
|
||||
Version.add(context.getString(R.string.details_rating, (app.getRating().getAverage())));
|
||||
if (PackageUtil.isInstalled(context, app.getPackageName()))
|
||||
Version.add(context.getString(R.string.action_installed));
|
||||
Extra.add(app.getPrice());
|
||||
Extra.add(context.getString(app.containsAds() ? R.string.list_app_has_ads : R.string.list_app_no_ads));
|
||||
Extra.add(context.getString(app.getDependencies().isEmpty() ? R.string.list_app_independent_from_gsf : R.string.list_app_depends_on_gsf));
|
||||
if (!StringUtils.isEmpty(app.getUpdated()))
|
||||
Extra.add(app.getUpdated());
|
||||
}
|
||||
}
|
||||
@@ -41,36 +41,36 @@ import butterknife.ButterKnife;
|
||||
|
||||
public class ExodusAdapter extends RecyclerView.Adapter<ExodusAdapter.ViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<ExodusTracker> mExodusTrackers;
|
||||
private Context context;
|
||||
private List<ExodusTracker> exodusTrackers;
|
||||
|
||||
public ExodusAdapter(Context mContext, List<ExodusTracker> mExodusTrackers) {
|
||||
this.mContext = mContext;
|
||||
this.mExodusTrackers = mExodusTrackers;
|
||||
public ExodusAdapter(Context context, List<ExodusTracker> exodusTrackers) {
|
||||
this.context = context;
|
||||
this.exodusTrackers = exodusTrackers;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_exodus, parent, false);
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_exodus, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
ExodusTracker mExodusTracker = mExodusTrackers.get(position);
|
||||
ExodusTracker mExodusTracker = exodusTrackers.get(position);
|
||||
holder.TrackerName.setText(mExodusTracker.Name);
|
||||
holder.TrackerSignature.setText(mExodusTracker.Signature);
|
||||
holder.TrackerDate.setText(mExodusTracker.Date);
|
||||
holder.itemView.setOnClickListener(v ->
|
||||
mContext.startActivity(new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse(mExodusTracker.URL)))
|
||||
holder.itemView.setOnClickListener(v -> context.startActivity(new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse(mExodusTracker.URL)))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mExodusTrackers.size();
|
||||
return exodusTrackers.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.manager.FavouriteListManager;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FavouriteAppsAdapter extends RecyclerView.Adapter {
|
||||
|
||||
private List<App> appList = new ArrayList<>();
|
||||
private List<App> selectedList = new ArrayList<>();
|
||||
private Context context;
|
||||
private FavouriteListManager manager;
|
||||
private SelectableViewHolder.ItemClickListener itemClickListener;
|
||||
|
||||
public FavouriteAppsAdapter(Context context, SelectableViewHolder.ItemClickListener itemClickListener, List<App> appsToAdd) {
|
||||
this.itemClickListener = itemClickListener;
|
||||
this.context = context;
|
||||
manager = new FavouriteListManager(context);
|
||||
appList.addAll(appsToAdd);
|
||||
Collections.sort(appsToAdd, (App1, App2) ->
|
||||
App1.getDisplayName().compareToIgnoreCase(App2.getDisplayName()));
|
||||
}
|
||||
|
||||
public void add(int position, App app) {
|
||||
appList.add(position, app);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
|
||||
public void add(App app) {
|
||||
appList.add(app);
|
||||
}
|
||||
|
||||
public void remove(int position) {
|
||||
manager.remove(appList.get(position).getPackageName());
|
||||
appList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return appList.isEmpty();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SelectableViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
View view = inflater.inflate(R.layout.item_favorite, parent, false);
|
||||
return new SelectableViewHolder(view, itemClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
||||
SelectableViewHolder holder = (SelectableViewHolder) viewHolder;
|
||||
App app = appList.get(position);
|
||||
|
||||
holder.AppTitle.setText(app.getDisplayName());
|
||||
|
||||
if (PackageUtil.isInstalled(context, app)) {
|
||||
holder.AppExtra.setText(context.getText(R.string.list_installed));
|
||||
holder.AppCheckbox.setEnabled(false);
|
||||
} else {
|
||||
holder.AppExtra.setText(context.getText(R.string.list_not_installd));
|
||||
}
|
||||
|
||||
Glide
|
||||
.with(context)
|
||||
.load(app.getIconInfo().getUrl())
|
||||
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
|
||||
.transition(new DrawableTransitionOptions().crossFade())
|
||||
.transforms(new CenterCrop(), new RoundedCorners(25))
|
||||
.into(holder.AppIcon);
|
||||
|
||||
holder.setChecked(isSelected(appList.get(position)));
|
||||
}
|
||||
|
||||
public void toggleSelection(int position) {
|
||||
App app = appList.get(position);
|
||||
if (selectedList.contains(app)) {
|
||||
selectedList.remove(app);
|
||||
} else {
|
||||
selectedList.add(app);
|
||||
}
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
private boolean isSelected(App app) {
|
||||
return selectedList.contains(app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
public List<App> getSelectedList() {
|
||||
return new ArrayList<>(selectedList);
|
||||
}
|
||||
}
|
||||
@@ -32,15 +32,18 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.CardType;
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.enums.CardType;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.ui.details.DetailsActivity;
|
||||
import com.aurora.store.util.PackageUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.aurora.store.util.ViewUtil;
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
@@ -88,18 +91,19 @@ public class FeaturedAppsAdapter extends RecyclerView.Adapter<FeaturedAppsAdapte
|
||||
if (app.getPageBackgroundImage() != null)
|
||||
drawBackground(app, viewHolder);
|
||||
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra("INTENT_PACKAGE_NAME", app.getPackageName());
|
||||
context.startActivity(intent);
|
||||
});
|
||||
|
||||
viewHolder.txtIndicator.setVisibility(PackageUtil.isInstalled(context, app)
|
||||
? View.VISIBLE
|
||||
: View.GONE);
|
||||
|
||||
if (viewHolder.txtSize != null)
|
||||
viewHolder.txtSize.setText(Util.humanReadableByteValue(app.getSize(), true));
|
||||
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
DetailsActivity.app = app;
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra(Constants.INTENT_PACKAGE_NAME, app.getPackageName());
|
||||
context.startActivity(intent, ViewUtil.getEmptyActivityBundle((AppCompatActivity) context));
|
||||
});
|
||||
}
|
||||
|
||||
private void drawBackground(App app, ViewHolder holder) {
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.ListType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.sheet.AppMenuSheet;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class InstalledAppsAdapter extends RecyclerView.Adapter<InstalledAppsAdapter.ViewHolder> {
|
||||
|
||||
public List<App> appList = new ArrayList<>();
|
||||
public Context context;
|
||||
private ListType listType;
|
||||
private AppMenuSheet menuSheet;
|
||||
|
||||
public InstalledAppsAdapter(Context context, ListType listType) {
|
||||
this.context = context;
|
||||
this.listType = listType;
|
||||
this.menuSheet = new AppMenuSheet();
|
||||
}
|
||||
|
||||
public void add(int position, App app) {
|
||||
appList.add(position, app);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
|
||||
public void add(App app) {
|
||||
appList.add(app);
|
||||
}
|
||||
|
||||
public void remove(int position) {
|
||||
appList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
public void remove(String packageName) {
|
||||
for (App app : appList) {
|
||||
if (app.getPackageName().equals(packageName)) {
|
||||
appList.remove(app);
|
||||
notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(App app) {
|
||||
appList.remove(app);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void addData(List<App> appList) {
|
||||
this.appList.clear();
|
||||
this.appList = appList;
|
||||
final Set<App> appSet = new LinkedHashSet<>(appList);
|
||||
appList.clear();
|
||||
appList.addAll(appSet);
|
||||
if (listType == ListType.INSTALLED || listType == ListType.UPDATES)
|
||||
Collections.sort(appList, (App1, App2) ->
|
||||
App1.getDisplayName().compareToIgnoreCase(App2.getDisplayName()));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean isDataEmpty() {
|
||||
return appList.isEmpty();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
View view = inflater.inflate(R.layout.item_installed, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
App app = appList.get(position);
|
||||
List<String> Version = new ArrayList<>();
|
||||
List<String> Extra = new ArrayList<>();
|
||||
|
||||
holder.AppTitle.setText(app.getDisplayName());
|
||||
getDetails(Version, Extra, app);
|
||||
setText(holder.AppExtra, TextUtils.join(" • ", Extra));
|
||||
setText(holder.AppVersion, TextUtils.join(" • ", Version));
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra("INTENT_PACKAGE_NAME", app.getPackageName());
|
||||
context.startActivity(intent);
|
||||
});
|
||||
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
menuSheet.setApp(app);
|
||||
menuSheet.setAdapter(this);
|
||||
menuSheet.show(getFragmentManager(), "BOTTOM_MENU_SHEET");
|
||||
return false;
|
||||
});
|
||||
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(app.getIconInfo().getUrl())
|
||||
.transition(new DrawableTransitionOptions().crossFade())
|
||||
.transforms(new CenterCrop(), new RoundedCorners(30))
|
||||
.into(holder.AppIcon);
|
||||
}
|
||||
|
||||
private FragmentManager getFragmentManager() {
|
||||
if (context instanceof DetailsActivity)
|
||||
return ((DetailsActivity) context).getSupportFragmentManager();
|
||||
else
|
||||
return ((AuroraActivity) context).getSupportFragmentManager();
|
||||
}
|
||||
|
||||
public void getDetails(List<String> Version, List<String> Extra, App app) {
|
||||
Version.add("v" + app.getVersionName() + "." + app.getVersionCode());
|
||||
if (app.isSystem())
|
||||
Extra.add(context.getString(R.string.list_app_system));
|
||||
else
|
||||
Extra.add(context.getString(R.string.list_app_user));
|
||||
}
|
||||
|
||||
protected void setText(TextView textView, String text) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
textView.setText(text);
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
textView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.app_icon)
|
||||
ImageView AppIcon;
|
||||
@BindView(R.id.app_title)
|
||||
TextView AppTitle;
|
||||
@BindView(R.id.app_version)
|
||||
TextView AppVersion;
|
||||
@BindView(R.id.app_extra)
|
||||
TextView AppExtra;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import com.aurora.store.exception.AppNotFoundException;
|
||||
import com.aurora.store.exception.MalformedRequestException;
|
||||
import com.aurora.store.exception.TooManyRequestsException;
|
||||
import com.aurora.store.exception.UnknownException;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.AuthException;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayException;
|
||||
@@ -46,7 +46,6 @@ import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class NativeHttpClientAdapter extends HttpClientAdapter {
|
||||
|
||||
@@ -81,13 +80,10 @@ public class NativeHttpClientAdapter extends HttpClientAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
static private byte[] readFully(InputStream inputStream, boolean gzipped) throws IOException {
|
||||
static private byte[] readFully(InputStream inputStream) throws IOException {
|
||||
if (null == inputStream) {
|
||||
return new byte[0];
|
||||
}
|
||||
if (gzipped) {
|
||||
inputStream = new GZIPInputStream(inputStream);
|
||||
}
|
||||
InputStream bufferedInputStream = new BufferedInputStream(inputStream);
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
@@ -177,8 +173,6 @@ public class NativeHttpClientAdapter extends HttpClientAdapter {
|
||||
protected byte[] request(HttpURLConnection connection, byte[] body, Map<String, String> headers) throws IOException {
|
||||
connection.setConnectTimeout(TIMEOUT);
|
||||
connection.setReadTimeout(TIMEOUT);
|
||||
connection.setRequestProperty("Accept-Encoding", "gzip");
|
||||
connection.addRequestProperty("Cache-Control", "max-age=300");
|
||||
for (String headerName : headers.keySet()) {
|
||||
connection.addRequestProperty(headerName, headers.get(headerName));
|
||||
}
|
||||
@@ -189,18 +183,11 @@ public class NativeHttpClientAdapter extends HttpClientAdapter {
|
||||
|
||||
int code = 0;
|
||||
|
||||
boolean isGzip;
|
||||
try {
|
||||
isGzip = null != connection.getContentEncoding() && connection.getContentEncoding().contains("gzip");
|
||||
} catch (NullPointerException e) {
|
||||
throw new AuthException(e.getMessage(), 401);
|
||||
}
|
||||
|
||||
try {
|
||||
code = connection.getResponseCode();
|
||||
content = readFully(connection.getInputStream(), isGzip);
|
||||
content = readFully(connection.getInputStream());
|
||||
} catch (IOException e) {
|
||||
content = readFully(connection.getErrorStream(), isGzip);
|
||||
content = readFully(connection.getErrorStream());
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.aurora.store.exception.AppNotFoundException;
|
||||
import com.aurora.store.exception.MalformedRequestException;
|
||||
import com.aurora.store.exception.TooManyRequestsException;
|
||||
import com.aurora.store.exception.UnknownException;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.AuthException;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayException;
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RatingBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.model.Review;
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class ReviewsAdapter extends RecyclerView.Adapter<ReviewsAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<Review> reviewList;
|
||||
|
||||
public ReviewsAdapter(Context context, List<Review> reviewList) {
|
||||
this.context = context;
|
||||
this.reviewList = reviewList;
|
||||
}
|
||||
|
||||
public void add(int position, Review review) {
|
||||
reviewList.add(position, review);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
|
||||
public void add(Review review) {
|
||||
reviewList.add(review);
|
||||
}
|
||||
|
||||
public void remove(int position) {
|
||||
reviewList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
public void sort() {
|
||||
Collections.sort(reviewList, (lhs, rhs) -> lhs.getRating() > rhs.getRating() ? -1 : 1);
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_review_list, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Review mReview = reviewList.get(position);
|
||||
holder.Author.setText(mReview.getUserName());
|
||||
holder.Rating.setRating(mReview.getRating());
|
||||
holder.Date.setText(getDate(mReview));
|
||||
holder.Comment.setText(mReview.getComment());
|
||||
|
||||
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(mReview.getUserPhotoUrl())
|
||||
.placeholder(R.color.colorTransparent)
|
||||
.circleCrop()
|
||||
.transition(new DrawableTransitionOptions().crossFade())
|
||||
.into(holder.Avatar);
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
MaterialAlertDialogBuilder mBuilder = new MaterialAlertDialogBuilder(context)
|
||||
.setIcon(holder.Avatar.getDrawable())
|
||||
.setTitle(mReview.getUserName())
|
||||
.setMessage(mReview.getComment())
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
mBuilder.create();
|
||||
mBuilder.show();
|
||||
});
|
||||
}
|
||||
|
||||
private String getDate(Review review) {
|
||||
Calendar calendar = Calendar.getInstance(Locale.getDefault());
|
||||
calendar.setTimeInMillis(review.getTimeStamp());
|
||||
return DateFormat.format("dd/MM/yyyy", calendar).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return reviewList.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.avatar)
|
||||
ImageView Avatar;
|
||||
@BindView(R.id.author)
|
||||
TextView Author;
|
||||
@BindView(R.id.rating)
|
||||
RatingBar Rating;
|
||||
@BindView(R.id.date)
|
||||
TextView Date;
|
||||
@BindView(R.id.comment)
|
||||
TextView Comment;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class SearchHistoryAdapter extends RecyclerView.Adapter<SearchHistoryAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private ArrayList<String> queryList;
|
||||
private ClickListener clickListener;
|
||||
|
||||
public SearchHistoryAdapter(Context context, ArrayList<String> queryList, ClickListener clickListener) {
|
||||
this.queryList = queryList;
|
||||
this.clickListener = clickListener;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void add(int position, String mHistory) {
|
||||
queryList.add(mHistory);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
|
||||
public void remove(int position) {
|
||||
queryList.remove(position);
|
||||
updatePrefList();
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
queryList.clear();
|
||||
clearPrefList();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
queryList = PrefUtil.getListString(context, Constants.RECENT_HISTORY);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void updatePrefList() {
|
||||
PrefUtil.putListString(context, Constants.RECENT_HISTORY, queryList);
|
||||
}
|
||||
|
||||
private void clearPrefList() {
|
||||
PrefUtil.putListString(context, Constants.RECENT_HISTORY, new ArrayList<>());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
View view = inflater.inflate(R.layout.item_history, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
|
||||
String[] datedQuery = queryList.get(position).split(":");
|
||||
holder.query.setText(datedQuery[0]);
|
||||
holder.date.setText(getQueryDate(datedQuery[1]));
|
||||
holder.viewForeground.setOnClickListener(v -> clickListener.onClicked(datedQuery[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return queryList.size();
|
||||
}
|
||||
|
||||
private String getQueryDate(String queryDate) {
|
||||
try {
|
||||
final long timeInMilli = Long.parseLong(queryDate);
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMM", Locale.getDefault());
|
||||
return simpleDateFormat.format(new Date(timeInMilli));
|
||||
} catch (NumberFormatException e) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ClickListener {
|
||||
void onClicked(String query);
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public RelativeLayout viewForeground;
|
||||
RelativeLayout viewBackground;
|
||||
TextView query;
|
||||
TextView date;
|
||||
|
||||
ViewHolder(View view) {
|
||||
super(view);
|
||||
query = view.findViewById(R.id.query);
|
||||
date = view.findViewById(R.id.queryTime);
|
||||
viewBackground = view.findViewById(R.id.view_background);
|
||||
viewForeground = view.findViewById(R.id.view_foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.dragons.aurora.playstoreapiv2.SearchSuggestEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class SearchSuggestionAdapter extends RecyclerView.Adapter<SearchSuggestionAdapter.ViewHolder> {
|
||||
|
||||
public List<SearchSuggestEntry> appList;
|
||||
public Context context;
|
||||
private ClickListener clickListener;
|
||||
|
||||
public SearchSuggestionAdapter(Context context, ClickListener clickListener) {
|
||||
this.context = context;
|
||||
this.clickListener = clickListener;
|
||||
this.appList = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addData(List<SearchSuggestEntry> appList) {
|
||||
this.appList.clear();
|
||||
this.appList.addAll(appList);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
View view = inflater.inflate(R.layout.item_suggestion, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
SearchSuggestEntry suggestEntry = appList.get(position);
|
||||
String title = suggestEntry.getTitle();
|
||||
String packageName = suggestEntry.getPackageNameContainer().getPackageName();
|
||||
holder.line1.setText(title);
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(suggestEntry.getImageContainer().getImageUrl())
|
||||
.placeholder(R.drawable.ic_round_search)
|
||||
.transforms(new CenterCrop(), new RoundedCorners(30))
|
||||
.into(holder.img);
|
||||
holder.itemView.setOnClickListener(v -> clickListener.onClickedSuggestion(packageName.isEmpty() ? title : packageName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
public interface ClickListener {
|
||||
void onClickedSuggestion(String query);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.img)
|
||||
ImageView img;
|
||||
@BindView(R.id.line1)
|
||||
TextView line1;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.manager.BlacklistManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
abstract class SelectableAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
|
||||
|
||||
protected ArrayList<String> mSelections;
|
||||
protected Context context;
|
||||
protected BlacklistManager mBlacklistManager;
|
||||
|
||||
SelectableAdapter(Context context) {
|
||||
this.context = context;
|
||||
mBlacklistManager = new BlacklistManager(context);
|
||||
ArrayList<String> blacklistedApps = mBlacklistManager.get();
|
||||
mSelections = new ArrayList<>();
|
||||
if (blacklistedApps != null && !blacklistedApps.isEmpty()) {
|
||||
mSelections.addAll(blacklistedApps);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isSelected(String packageName) {
|
||||
return mSelections.contains(packageName);
|
||||
}
|
||||
|
||||
void toggleSelection(int position) {
|
||||
}
|
||||
|
||||
public void addSelectionsToBlackList() {
|
||||
mBlacklistManager.addAll(mSelections);
|
||||
}
|
||||
|
||||
public void removeSelectionsFromBlackList() {
|
||||
mBlacklistManager.removeAll(mSelections);
|
||||
mSelections = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class SelectableViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
@BindView(R.id.view_foreground)
|
||||
public RelativeLayout viewForeground;
|
||||
@BindView(R.id.view_background)
|
||||
RelativeLayout viewBackground;
|
||||
@BindView(R.id.app_icon)
|
||||
ImageView AppIcon;
|
||||
@BindView(R.id.app_title)
|
||||
TextView AppTitle;
|
||||
@BindView(R.id.app_extra)
|
||||
TextView AppExtra;
|
||||
@BindView(R.id.app_checkbox)
|
||||
CheckBox AppCheckbox;
|
||||
|
||||
private ItemClickListener listener;
|
||||
|
||||
SelectableViewHolder(View view, ItemClickListener listener) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, view);
|
||||
this.listener = listener;
|
||||
view.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void setChecked(boolean value) {
|
||||
AppCheckbox.setChecked(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.onItemClicked(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClicked(int position);
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.FullscreenImageActivity;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.aurora.store.ui.single.activity.FullscreenImageActivity;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.fragment.SubCategoryFragment;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SubCategoryAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private Context context;
|
||||
|
||||
public SubCategoryAdapter(Context context, FragmentManager fragmentManager) {
|
||||
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
final Bundle bundle = new Bundle();
|
||||
final Fragment subCategoryFragment = new SubCategoryFragment();
|
||||
switch (position) {
|
||||
case 0:
|
||||
bundle.putString("SUBCATEGORY", "TOP_FREE");
|
||||
break;
|
||||
case 1:
|
||||
bundle.putString("SUBCATEGORY", "MOVERS_SHAKERS");
|
||||
break;
|
||||
default:
|
||||
bundle.putString("SUBCATEGORY", "TOP_GROSSING");
|
||||
break;
|
||||
}
|
||||
subCategoryFragment.setArguments(bundle);
|
||||
return subCategoryFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return context.getString(R.string.category_topFree);
|
||||
case 1:
|
||||
return context.getString(R.string.category_trending);
|
||||
default:
|
||||
return context.getString(R.string.category_topGrossing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TabAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private final List<Fragment> fragmentList = new ArrayList<>();
|
||||
private final List<String> fragmentTitleList = new ArrayList<>();
|
||||
|
||||
public TabAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return fragmentList.get(position);
|
||||
}
|
||||
|
||||
public void addFragment(Fragment fragment, String title) {
|
||||
fragmentList.add(fragment);
|
||||
fragmentTitleList.add(title);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return fragmentTitleList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return fragmentList.size();
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.SharedPreferencesTranslator;
|
||||
import com.aurora.store.fragment.CategoriesFragment;
|
||||
import com.aurora.store.fragment.CategoryAppsFragment;
|
||||
import com.aurora.store.fragment.HomeFragment;
|
||||
import com.aurora.store.utility.ColorUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class TopCategoriesAdapter extends RecyclerView.Adapter<TopCategoriesAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private Fragment fragment;
|
||||
private String[] topCategoryIDs;
|
||||
private SharedPreferencesTranslator translator;
|
||||
private boolean isTransparent;
|
||||
|
||||
private Integer[] categoriesImg = {
|
||||
R.drawable.ic_cat_communication,
|
||||
R.drawable.ic_cat_family,
|
||||
R.drawable.ic_cat_games,
|
||||
R.drawable.ic_cat_music,
|
||||
R.drawable.ic_cat_personalization,
|
||||
R.drawable.ic_cat_photography,
|
||||
R.drawable.ic_cat_shopping,
|
||||
R.drawable.ic_cat_social_alt,
|
||||
};
|
||||
|
||||
public TopCategoriesAdapter(HomeFragment fragment) {
|
||||
this.fragment = fragment;
|
||||
this.context = fragment.getContext();
|
||||
this.topCategoryIDs = context.getResources().getStringArray(R.array.topCategories);
|
||||
this.isTransparent = Util.isTransparentStyle(context);
|
||||
this.translator = new SharedPreferencesTranslator(Util.getPrefs(context));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_category_top, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
|
||||
@ColorInt int color = ViewUtil.getSolidColors(position);
|
||||
holder.itemView.setBackgroundTintList(ColorStateList.valueOf(
|
||||
ColorUtils.setAlphaComponent(color, isTransparent ? 60 : 255)));
|
||||
holder.imgCat.setImageDrawable(context.getResources().getDrawable(categoriesImg[position]));
|
||||
holder.imgCat.setColorFilter(isTransparent ? ColorUtil.manipulateColor(color, 0.85f) : Color.WHITE);
|
||||
holder.txtCat.setText(translator.getString(topCategoryIDs[position]));
|
||||
holder.txtCat.setTextColor(isTransparent ? ColorUtil.manipulateColor(color, 0.75f) : Color.WHITE);
|
||||
|
||||
if (topCategoryIDs[position].equals(CategoriesFragment.FAMILY)) {
|
||||
holder.itemView.setOnClickListener(v -> getSubCategoryFragment(CategoriesFragment.FAMILY));
|
||||
} else if (topCategoryIDs[position].equals(CategoriesFragment.GAME)) {
|
||||
holder.itemView.setOnClickListener(v -> getSubCategoryFragment(CategoriesFragment.GAME));
|
||||
} else
|
||||
holder.itemView.setOnClickListener(v -> getCategoryAppsFragment(position));
|
||||
}
|
||||
|
||||
private void getSubCategoryFragment(String subCategory) {
|
||||
CategoriesFragment categoryAppsFragment = new CategoriesFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("CATEGORY_TYPE", subCategory);
|
||||
categoryAppsFragment.setArguments(arguments);
|
||||
fragment.getChildFragmentManager().beginTransaction()
|
||||
.replace(R.id.coordinator, categoryAppsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void getCategoryAppsFragment(int position) {
|
||||
CategoryAppsFragment categoryAppsFragment = new CategoryAppsFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("CategoryId", topCategoryIDs[position]);
|
||||
arguments.putString("CategoryName", translator.getString(topCategoryIDs[position]));
|
||||
categoryAppsFragment.setArguments(arguments);
|
||||
fragment.getChildFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.coordinator, categoryAppsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return topCategoryIDs.length;
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@BindView(R.id.cat_icon)
|
||||
ImageView imgCat;
|
||||
@BindView(R.id.cat_txt)
|
||||
TextView txtCat;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.Formatter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.sheet.AppMenuSheet;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class UpdatableAppsAdapter extends RecyclerView.Adapter<UpdatableAppsAdapter.ViewHolder> {
|
||||
|
||||
private List<App> appList = new ArrayList<>();
|
||||
private Context context;
|
||||
private AppMenuSheet menuSheet;
|
||||
|
||||
public UpdatableAppsAdapter(Context context) {
|
||||
this.context = context;
|
||||
this.menuSheet = new AppMenuSheet();
|
||||
}
|
||||
|
||||
public List<App> getAppList() {
|
||||
return appList;
|
||||
}
|
||||
|
||||
public void add(int position, App app) {
|
||||
appList.add(position, app);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
|
||||
public void add(App app) {
|
||||
appList.add(app);
|
||||
}
|
||||
|
||||
public void remove(int position) {
|
||||
appList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
public void remove(String packageName) {
|
||||
Iterator<App> iterator = appList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final App app = iterator.next();
|
||||
if (packageName.equals(app.getPackageName()) || packageName.startsWith(app.getPackageName()))
|
||||
iterator.remove();
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void remove(App app) {
|
||||
appList.remove(app);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void addData(List<App> appList) {
|
||||
this.appList.clear();
|
||||
this.appList = appList;
|
||||
Collections.sort(appList, (App1, App2) ->
|
||||
App1.getDisplayName().compareToIgnoreCase(App2.getDisplayName()));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean isDataEmpty() {
|
||||
return appList.isEmpty();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
View view = inflater.inflate(R.layout.item_updatable, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
|
||||
App app = appList.get(position);
|
||||
List<String> Version = new ArrayList<>();
|
||||
List<String> Extra = new ArrayList<>();
|
||||
|
||||
viewHolder.txtTitle.setText(app.getDisplayName());
|
||||
getDetails(Version, Extra, app);
|
||||
setText(viewHolder.txtVersion, TextUtils.join(" • ", Version));
|
||||
setText(viewHolder.txtExtra, TextUtils.join(" • ", Extra));
|
||||
setText(viewHolder.txtChanges, app.getChanges().isEmpty()
|
||||
? context.getString(R.string.details_no_changes)
|
||||
: Html.fromHtml(app.getChanges()).toString());
|
||||
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra("INTENT_PACKAGE_NAME", app.getPackageName());
|
||||
context.startActivity(intent);
|
||||
});
|
||||
|
||||
viewHolder.itemView.setOnLongClickListener(v -> {
|
||||
menuSheet.setApp(app);
|
||||
menuSheet.setAdapter(this);
|
||||
menuSheet.show(((AuroraActivity) context).getSupportFragmentManager(),
|
||||
"BOTTOM_MENU_SHEET");
|
||||
return false;
|
||||
});
|
||||
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(app.getIconInfo().getUrl())
|
||||
.transition(new DrawableTransitionOptions().crossFade())
|
||||
.transforms(new CenterCrop(), new RoundedCorners(25))
|
||||
.into(viewHolder.imgIcon);
|
||||
|
||||
viewHolder.imgExpand.setOnClickListener(v -> {
|
||||
if (viewHolder.layoutChanges.getHeight() == 0) {
|
||||
ViewUtil.rotateView(v, false);
|
||||
ViewUtil.expandView(viewHolder.layoutChanges,
|
||||
viewHolder.txtChanges.getHeight()
|
||||
+ viewHolder.txtChangesTitle.getHeight()
|
||||
+ 120 /*Padding & Margins*/);
|
||||
} else {
|
||||
ViewUtil.rotateView(v, true);
|
||||
ViewUtil.collapseView(viewHolder.layoutChanges, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getDetails(List<String> Version, List<String> Extra, App app) {
|
||||
Version.add(app.getUpdated());
|
||||
Extra.add(app.getSize() == 0 ? "N/A" : Formatter.formatShortFileSize(context, app.getSize()));
|
||||
}
|
||||
|
||||
protected void setText(TextView textView, String text) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
textView.setText(text);
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
textView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.layout_info)
|
||||
RelativeLayout layoutInfo;
|
||||
@BindView(R.id.layout_changes)
|
||||
RelativeLayout layoutChanges;
|
||||
@BindView(R.id.app_icon)
|
||||
ImageView imgIcon;
|
||||
@BindView(R.id.app_title)
|
||||
TextView txtTitle;
|
||||
@BindView(R.id.app_version)
|
||||
TextView txtVersion;
|
||||
@BindView(R.id.app_extra)
|
||||
TextView txtExtra;
|
||||
@BindView(R.id.img_expand)
|
||||
ImageView imgExpand;
|
||||
@BindView(R.id.txt_title)
|
||||
TextView txtChangesTitle;
|
||||
@BindView(R.id.txt_changes)
|
||||
TextView txtChanges;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.aurora.store.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private List<Fragment> fragmentList = new ArrayList<>();
|
||||
|
||||
public ViewPagerAdapter(@NonNull FragmentManager fragmentManager) {
|
||||
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
}
|
||||
|
||||
public void addFragment(int position, Fragment fragment) {
|
||||
fragmentList.add(position, fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return fragmentList.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return fragmentList.get(position);
|
||||
}
|
||||
}
|
||||
@@ -27,62 +27,33 @@ import android.content.Context;
|
||||
|
||||
import com.aurora.store.TokenDispenserMirrors;
|
||||
import com.aurora.store.model.LoginInfo;
|
||||
import com.aurora.store.utility.ApiBuilderUtil;
|
||||
import com.aurora.store.util.ApiBuilderUtil;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PlayStoreApiAuthenticator {
|
||||
|
||||
private static volatile PlayStoreApiAuthenticator instance;
|
||||
private static GooglePlayAPI api;
|
||||
|
||||
public PlayStoreApiAuthenticator() {
|
||||
if (instance != null) {
|
||||
throw new RuntimeException("Use getApi() method to get the single instance of RxBus");
|
||||
}
|
||||
}
|
||||
|
||||
public static GooglePlayAPI getApi() {
|
||||
return api;
|
||||
}
|
||||
|
||||
public static GooglePlayAPI getInstance(Context context) throws Exception {
|
||||
if (instance == null) {
|
||||
synchronized (PlayStoreApiAuthenticator.class) {
|
||||
if (instance == null) {
|
||||
instance = new PlayStoreApiAuthenticator();
|
||||
api = instance.getApi(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return api;
|
||||
}
|
||||
|
||||
public static boolean login(Context context, String email, String password) throws IOException {
|
||||
LoginInfo loginInfo = new LoginInfo();
|
||||
loginInfo.setEmail(email);
|
||||
loginInfo.setAasToken(password);
|
||||
GooglePlayAPI api = ApiBuilderUtil.buildApi(context, loginInfo);
|
||||
GooglePlayAPI api = ApiBuilderUtil.buildApi(context, loginInfo, false);
|
||||
return api != null;
|
||||
}
|
||||
|
||||
public static GooglePlayAPI login(Context context) throws IOException {
|
||||
LoginInfo loginInfo = new LoginInfo();
|
||||
loginInfo.setTokenDispenserUrl(TokenDispenserMirrors.get(context));
|
||||
GooglePlayAPI api = ApiBuilderUtil.buildAnonymousApi(context, loginInfo);
|
||||
return api;
|
||||
return ApiBuilderUtil.buildApi(context, loginInfo, true);
|
||||
}
|
||||
|
||||
public static void destroyInstance() {
|
||||
api = null;
|
||||
instance = null;
|
||||
public static GooglePlayAPI getApi(Context context) throws Exception {
|
||||
return ApiBuilderUtil.buildFromPreferences(context);
|
||||
}
|
||||
|
||||
private synchronized GooglePlayAPI getApi(Context context) throws Exception {
|
||||
if (api == null) {
|
||||
api = ApiBuilderUtil.buildFromPreferences(context);
|
||||
}
|
||||
return api;
|
||||
public GooglePlayAPI getPlayApi(Context context) throws Exception {
|
||||
return ApiBuilderUtil.buildFromPreferences(context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ package com.aurora.store.download;
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.tonyodev.fetch2.Fetch;
|
||||
import com.tonyodev.fetch2.FetchConfiguration;
|
||||
import com.tonyodev.fetch2okhttp.OkHttpDownloader;
|
||||
|
||||
@@ -23,9 +23,9 @@ package com.aurora.store.download;
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.PathUtil;
|
||||
import com.aurora.store.utility.TextUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.PathUtil;
|
||||
import com.aurora.store.util.TextUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.AndroidAppDeliveryData;
|
||||
import com.dragons.aurora.playstoreapiv2.AppFileMetadata;
|
||||
import com.dragons.aurora.playstoreapiv2.Split;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
package com.aurora.store.enums;
|
||||
|
||||
public enum CardType {
|
||||
LEGACY,
|
||||
@@ -18,17 +18,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
package com.aurora.store.enums;
|
||||
|
||||
public enum ErrorType {
|
||||
NO_NETWORK,
|
||||
NO_APPS,
|
||||
NO_UPDATES,
|
||||
NO_SEARCH,
|
||||
NO_DOWNLOADS,
|
||||
NO_API,
|
||||
UNKNOWN,
|
||||
SESSION_EXPIRED,
|
||||
APP_NOT_FOUND,
|
||||
LOGOUT_ERR,
|
||||
IMPORT
|
||||
LOGOUT_ERR
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store;
|
||||
package com.aurora.store.enums;
|
||||
|
||||
public enum NotificationProvider {
|
||||
NATIVE,
|
||||
@@ -1,18 +1,40 @@
|
||||
package com.aurora.store.events;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class Event {
|
||||
|
||||
private Events event;
|
||||
private SubType subType;
|
||||
private String packageName;
|
||||
private int status;
|
||||
|
||||
public Event(Events event) {
|
||||
this.event = event;
|
||||
public Event(SubType subType, String packageName, int status) {
|
||||
this.subType = subType;
|
||||
this.packageName = packageName;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Events getEvent() {
|
||||
return event;
|
||||
public Event(SubType subType, String packageName) {
|
||||
this.subType = subType;
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setEvent(Events event) {
|
||||
this.event = event;
|
||||
public Event(SubType subType) {
|
||||
this.subType = subType;
|
||||
}
|
||||
|
||||
public enum SubType {
|
||||
API_SUCCESS,
|
||||
API_FAILED,
|
||||
API_ERROR,
|
||||
BLACKLIST,
|
||||
WHITELIST,
|
||||
INSTALLED,
|
||||
UNINSTALLED,
|
||||
NETWORK_UNAVAILABLE,
|
||||
NETWORK_AVAILABLE,
|
||||
BULK_UPDATE_NOTIFY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.aurora.store.events;
|
||||
|
||||
public enum Events {
|
||||
LOGGED_IN,
|
||||
LOGGED_OUT,
|
||||
TOKEN_REFRESHED,
|
||||
TOKEN_EXPIRED,
|
||||
NET_CONNECTED,
|
||||
NET_DISCONNECTED,
|
||||
PERMANENT_FAIL,
|
||||
BLACKLIST
|
||||
}
|
||||
@@ -3,38 +3,11 @@ package com.aurora.store.events;
|
||||
import com.jakewharton.rxrelay2.PublishRelay;
|
||||
import com.jakewharton.rxrelay2.Relay;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class RxBus {
|
||||
|
||||
public static volatile RxBus instance;
|
||||
private final Relay<Object> bus = PublishRelay.create().toSerialized();
|
||||
private final Relay<Event> bus = PublishRelay.create();
|
||||
|
||||
public RxBus() {
|
||||
if (instance != null) {
|
||||
throw new RuntimeException("Use get() method to get the single instance of RxBus");
|
||||
}
|
||||
}
|
||||
|
||||
public static RxBus get() {
|
||||
if (instance == null) {
|
||||
synchronized (RxBus.class) {
|
||||
if (instance == null) instance = new RxBus();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void publish(Object event) {
|
||||
RxBus auroraBus = RxBus.get();
|
||||
auroraBus.bus.accept(event);
|
||||
}
|
||||
|
||||
public Observable<Object> toObservable() {
|
||||
public Relay<Event> getBus() {
|
||||
return bus;
|
||||
}
|
||||
|
||||
public boolean hasObservers() {
|
||||
return bus.hasObservers();
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.adapter.TabAdapter;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class AppsFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.tabLayout)
|
||||
TabLayout mTabLayout;
|
||||
@BindView(R.id.tabPager)
|
||||
ViewPager mViewPager;
|
||||
private Context context;
|
||||
|
||||
@Override
|
||||
public void onAttach(@NotNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
View view = inflater.inflate(R.layout.fragment_apps, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
TabAdapter mTabAdapter = new TabAdapter(getChildFragmentManager());
|
||||
mTabAdapter.addFragment(new UpdatesFragment(), getString(R.string.action_updates));
|
||||
mTabAdapter.addFragment(new InstalledFragment(), getString(R.string.action_installed));
|
||||
|
||||
mViewPager.setAdapter(mTabAdapter);
|
||||
mViewPager.setOffscreenPageLimit(3);
|
||||
mTabLayout.setupWithViewPager(mViewPager);
|
||||
mTabLayout.setTabMode(Util.isTabScrollable(context)
|
||||
? TabLayout.MODE_SCROLLABLE
|
||||
: TabLayout.MODE_FIXED);
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ViewSwitcher;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.aurora.store.AnonymousLoginService;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AccountsActivity;
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.events.Event;
|
||||
import com.aurora.store.events.Events;
|
||||
import com.aurora.store.events.RxBus;
|
||||
import com.aurora.store.exception.CredentialsEmptyException;
|
||||
import com.aurora.store.exception.InvalidApiException;
|
||||
import com.aurora.store.exception.MalformedRequestException;
|
||||
import com.aurora.store.exception.TooManyRequestsException;
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.view.ErrorView;
|
||||
import com.dragons.aurora.playstoreapiv2.AuthException;
|
||||
import com.dragons.aurora.playstoreapiv2.IteratorGooglePlayException;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import butterknife.BindView;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static com.aurora.store.utility.Util.noNetwork;
|
||||
|
||||
public abstract class BaseFragment extends Fragment {
|
||||
|
||||
protected CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
@BindView(R.id.coordinator)
|
||||
CoordinatorLayout coordinatorLayout;
|
||||
@BindView(R.id.view_switcher)
|
||||
ViewSwitcher viewSwitcher;
|
||||
@BindView(R.id.content_view)
|
||||
ViewGroup layoutContent;
|
||||
@BindView(R.id.err_view)
|
||||
ViewGroup layoutError;
|
||||
|
||||
private CompositeDisposable disposableBus = new CompositeDisposable();
|
||||
private Context context;
|
||||
|
||||
protected abstract View.OnClickListener errRetry();
|
||||
|
||||
protected abstract void fetchData();
|
||||
|
||||
/*UI handling methods*/
|
||||
|
||||
protected void notifyLoggedIn() {
|
||||
ContextUtil.runOnUiThread(() -> {
|
||||
fetchData();
|
||||
notifyStatus(coordinatorLayout, context.getResources().getString(R.string.action_logging_in_success));
|
||||
});
|
||||
}
|
||||
|
||||
protected void notifyNetworkFailure() {
|
||||
setErrorView(ErrorType.NO_NETWORK);
|
||||
notifyStatus(coordinatorLayout, context.getString(R.string.error_no_network));
|
||||
switchViews(true);
|
||||
}
|
||||
|
||||
protected void notifyPermanentFailure() {
|
||||
setErrorView(ErrorType.UNKNOWN);
|
||||
switchViews(true);
|
||||
}
|
||||
|
||||
protected void notifyLoggedOut() {
|
||||
setErrorView(ErrorType.LOGOUT_ERR);
|
||||
switchViews(true);
|
||||
notifyStatus(coordinatorLayout, context.getString(R.string.error_logged_out));
|
||||
}
|
||||
|
||||
protected void notifyTokenExpired() {
|
||||
setErrorView(ErrorType.SESSION_EXPIRED);
|
||||
switchViews(true);
|
||||
notifyStatus(coordinatorLayout, context.getString(R.string.action_token_expired));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
disposableBus.add(RxBus.get().toObservable()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(event -> {
|
||||
if (event instanceof Event) {
|
||||
Events eventEnum = ((Event) event).getEvent();
|
||||
switch (eventEnum) {
|
||||
case LOGGED_IN:
|
||||
case TOKEN_REFRESHED:
|
||||
notifyLoggedIn();
|
||||
break;
|
||||
case LOGGED_OUT:
|
||||
notifyLoggedOut();
|
||||
break;
|
||||
case TOKEN_EXPIRED:
|
||||
notifyTokenExpired();
|
||||
break;
|
||||
case NET_DISCONNECTED:
|
||||
notifyNetworkFailure();
|
||||
break;
|
||||
case PERMANENT_FAIL:
|
||||
notifyPermanentFailure();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
disposableBus.clear();
|
||||
}
|
||||
|
||||
private void notifyStatus(@NonNull CoordinatorLayout coordinatorLayout, String message) {
|
||||
Snackbar snackbar = Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG);
|
||||
snackbar.show();
|
||||
}
|
||||
|
||||
/*ErrorView UI handling methods*/
|
||||
|
||||
protected void setErrorView(ErrorType errorType) {
|
||||
layoutError.removeAllViews();
|
||||
layoutError.addView(new ErrorView(context, errorType, getAction(errorType)));
|
||||
}
|
||||
|
||||
protected void switchViews(boolean showError) {
|
||||
if (viewSwitcher.getCurrentView() == layoutContent && showError)
|
||||
viewSwitcher.showNext();
|
||||
else if (viewSwitcher.getCurrentView() == layoutError && !showError)
|
||||
viewSwitcher.showPrevious();
|
||||
}
|
||||
|
||||
private View.OnClickListener errLogin() {
|
||||
return v -> {
|
||||
((Button) v).setText(getString(R.string.action_logging_in));
|
||||
((Button) v).setEnabled(false);
|
||||
if (Accountant.isLoggedIn(context)) {
|
||||
RxBus.publish(new Event(Events.LOGGED_IN));
|
||||
return;
|
||||
}
|
||||
context.startActivity(new Intent(context, AccountsActivity.class));
|
||||
};
|
||||
}
|
||||
|
||||
protected View.OnClickListener errClose() {
|
||||
return v -> {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private View.OnClickListener getAction(ErrorType errorType) {
|
||||
switch (errorType) {
|
||||
case LOGOUT_ERR:
|
||||
return errLogin();
|
||||
case APP_NOT_FOUND:
|
||||
return errClose();
|
||||
default:
|
||||
return errRetry();
|
||||
}
|
||||
}
|
||||
|
||||
/*Exception handling methods*/
|
||||
|
||||
protected void processException(Throwable e) {
|
||||
if (e instanceof AuthException) {
|
||||
processAuthException((AuthException) e);
|
||||
} else if (e instanceof IteratorGooglePlayException) {
|
||||
processException(e.getCause());
|
||||
} else if (e instanceof TooManyRequestsException) {
|
||||
processAuthException(new AuthException("Too many request", 429));
|
||||
} else if (e instanceof MalformedRequestException) {
|
||||
processAuthException(new AuthException("Malformed Request", 401));
|
||||
} else if (e instanceof IOException) {
|
||||
processIOException((IOException) e);
|
||||
} else {
|
||||
Log.e("Unknown exception " + e.getClass().getName() + " " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void processIOException(IOException e) {
|
||||
String message;
|
||||
if (noNetwork(e)) {
|
||||
message = context.getString(R.string.error_no_network);
|
||||
Log.i(message);
|
||||
RxBus.publish(new Event(Events.NET_DISCONNECTED));
|
||||
} else {
|
||||
message = TextUtils.isEmpty(e.getMessage())
|
||||
? context.getString(R.string.error_network_other)
|
||||
: e.getMessage();
|
||||
Log.i(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void processAuthException(AuthException e) {
|
||||
PlayStoreApiAuthenticator.destroyInstance();
|
||||
if (e instanceof CredentialsEmptyException || e instanceof InvalidApiException) {
|
||||
Accountant.completeCheckout(context);
|
||||
RxBus.publish(new Event(Events.LOGGED_OUT));
|
||||
} else if (e.getCode() >= 400 && Accountant.isAnonymous(context)) {
|
||||
RxBus.publish(new Event(Events.TOKEN_EXPIRED));
|
||||
Accountant.completeCheckout(context);
|
||||
logInWithDummy();
|
||||
} else {
|
||||
ContextUtil.toast(context, R.string.error_session_expired);
|
||||
Accountant.completeCheckout(context);
|
||||
}
|
||||
}
|
||||
|
||||
private void logInWithDummy() {
|
||||
Intent intent = new Intent(context, AnonymousLoginService.class);
|
||||
if (!AnonymousLoginService.isServiceRunning())
|
||||
context.startService(intent);
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.adapter.CategoriesListAdapter;
|
||||
import com.aurora.store.manager.CategoryManager;
|
||||
import com.aurora.store.task.CategoryList;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class CategoriesFragment extends Fragment {
|
||||
|
||||
public static final String APPS = "APPLICATION";
|
||||
public static final String GAME = "GAME";
|
||||
public static final String FAMILY = "FAMILY";
|
||||
|
||||
|
||||
@BindView(R.id.category_recycler)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
private Context context;
|
||||
private CategoryManager categoryManager;
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
private CategoriesListAdapter categoriesListAdapter;
|
||||
private String categoryType = APPS;
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
categoryManager = new CategoryManager(context);
|
||||
categoriesListAdapter = new CategoriesListAdapter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
View view = inflater.inflate(R.layout.fragment_categories, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
categoryType = arguments.getString("CATEGORY_TYPE");
|
||||
setupAllCategories();
|
||||
} else
|
||||
Log.e("No category id provided");
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (categoriesListAdapter == null || categoriesListAdapter.isDataEmpty())
|
||||
getCategories();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Glide.with(this).pauseAllRequests();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void setupAllCategories() {
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(context, getSpanCount()));
|
||||
recyclerView.setAdapter(categoriesListAdapter);
|
||||
}
|
||||
|
||||
private int getSpanCount() {
|
||||
int width = Resources.getSystem().getConfiguration().screenWidthDp;
|
||||
return width / 200;
|
||||
}
|
||||
|
||||
private void getCategories() {
|
||||
if (categoryManager.categoryListEmpty()) {
|
||||
getCategoriesFromAPI();
|
||||
return;
|
||||
}
|
||||
switch (categoryType) {
|
||||
case APPS:
|
||||
categoriesListAdapter.addData(categoryManager.getAllCategories());
|
||||
break;
|
||||
case GAME:
|
||||
categoriesListAdapter.addData(categoryManager.getAllGames());
|
||||
break;
|
||||
case FAMILY:
|
||||
categoriesListAdapter.addData(categoryManager.getAllFamily());
|
||||
break;
|
||||
default:
|
||||
categoriesListAdapter.addData(categoryManager.getAllCategories());
|
||||
}
|
||||
}
|
||||
|
||||
private void getCategoriesFromAPI() {
|
||||
disposable.add(Observable.fromCallable(() -> new CategoryList(context)
|
||||
.getResult())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((success) -> {
|
||||
if (success) {
|
||||
Log.i("CategoryList fetch completed");
|
||||
ContextUtil.runOnUiThread(() -> {
|
||||
getCategories();
|
||||
Log.i("Categories populated");
|
||||
});
|
||||
}
|
||||
}, err -> Log.e(err.getMessage())));
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.aurora.store.Filter;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.adapter.SubCategoryAdapter;
|
||||
import com.aurora.store.sheet.FilterBottomSheet;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class CategoryAppsFragment extends Fragment {
|
||||
|
||||
public static String categoryId;
|
||||
|
||||
@BindView(R.id.view_pager)
|
||||
ViewPager viewPager;
|
||||
@BindView(R.id.category_tabs)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.filter_fab)
|
||||
ExtendedFloatingActionButton filterFab;
|
||||
|
||||
private Context context;
|
||||
private ActionBar actionBar;
|
||||
|
||||
public ExtendedFloatingActionButton getFilterFab() {
|
||||
return filterFab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
View view = inflater.inflate(R.layout.fragment_category_container, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
categoryId = arguments.getString("CategoryId");
|
||||
if (getActivity() instanceof AuroraActivity) {
|
||||
actionBar = ((AuroraActivity) getActivity()).getSupportActionBar();
|
||||
actionBar.setTitle(arguments.getString("CategoryName"));
|
||||
}
|
||||
} else
|
||||
Log.e("No category id provided");
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
SubCategoryAdapter subCategoryAdapter = new SubCategoryAdapter(getContext(), getChildFragmentManager());
|
||||
viewPager.setAdapter(subCategoryAdapter);
|
||||
viewPager.setOffscreenPageLimit(2);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
filterFab.setOnClickListener(v -> {
|
||||
getFilterDialog();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Glide.with(this).pauseAllRequests();
|
||||
if (actionBar != null)
|
||||
actionBar.setTitle(getString(R.string.app_name));
|
||||
if (Util.filterSearchNonPersistent(context))
|
||||
new Filter(context).resetFilterPreferences();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void getFilterDialog() {
|
||||
FilterBottomSheet filterSheet = new FilterBottomSheet();
|
||||
filterSheet.setOnApplyListener(v -> {
|
||||
filterSheet.dismiss();
|
||||
viewPager.removeAllViews();
|
||||
viewPager.setAdapter(new SubCategoryAdapter(getContext(), getChildFragmentManager()));
|
||||
});
|
||||
filterSheet.show(getChildFragmentManager(), "FILTER");
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.exception.AppNotFoundException;
|
||||
import com.aurora.store.fragment.details.AbstractHelper;
|
||||
import com.aurora.store.fragment.details.ActionButton;
|
||||
import com.aurora.store.fragment.details.AppLinks;
|
||||
import com.aurora.store.fragment.details.Beta;
|
||||
import com.aurora.store.fragment.details.ExodusPrivacy;
|
||||
import com.aurora.store.fragment.details.GeneralDetails;
|
||||
import com.aurora.store.fragment.details.Reviews;
|
||||
import com.aurora.store.fragment.details.Screenshot;
|
||||
import com.aurora.store.fragment.details.Video;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.DetailsApp;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class DetailsFragment extends BaseFragment {
|
||||
|
||||
private static final String ACTION_PACKAGE_REPLACED_NON_SYSTEM = "ACTION_PACKAGE_REPLACED_NON_SYSTEM";
|
||||
private static final String ACTION_PACKAGE_INSTALLATION_FAILED = "ACTION_PACKAGE_INSTALLATION_FAILED";
|
||||
private static final String ACTION_UNINSTALL_PACKAGE_FAILED = "ACTION_UNINSTALL_PACKAGE_FAILED";
|
||||
|
||||
public static App app;
|
||||
|
||||
@BindView(R.id.scroll_view)
|
||||
NestedScrollView mScrollView;
|
||||
|
||||
private Context context;
|
||||
private ActionButton actionButton;
|
||||
private String packageName;
|
||||
|
||||
private BroadcastReceiver localInstallReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String packageName = intent.getStringExtra("PACKAGE_NAME");
|
||||
int statusCode = intent.getIntExtra("STATUS_CODE", -1);
|
||||
if (packageName != null && packageName.equals(app.getPackageName()))
|
||||
ContextUtil.runOnUiThread(() -> drawButtons());
|
||||
if (statusCode == 0)
|
||||
ContextUtil.toastLong(context, getString(R.string.installer_status_failure));
|
||||
}
|
||||
};
|
||||
|
||||
private BroadcastReceiver globalInstallReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getData() == null || !TextUtils.equals(packageName, intent.getData().getSchemeSpecificPart())) {
|
||||
return;
|
||||
}
|
||||
ContextUtil.runOnUiThread(() -> drawButtons());
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_details, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
setErrorView(ErrorType.NO_APPS);
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
packageName = arguments.getString("PackageName");
|
||||
fetchData();
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
context.registerReceiver(localInstallReceiver, new IntentFilter("ACTION_INSTALL"));
|
||||
context.registerReceiver(globalInstallReceiver, getFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
try {
|
||||
context.unregisterReceiver(localInstallReceiver);
|
||||
context.unregisterReceiver(globalInstallReceiver);
|
||||
disposable.clear();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
disposable.add(Observable.fromCallable(() -> new DetailsApp(getContext())
|
||||
.getInfo(packageName))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(app -> {
|
||||
switchViews(false);
|
||||
draw(app);
|
||||
}, err -> {
|
||||
Log.e(err.getMessage());
|
||||
processException(err);
|
||||
}));
|
||||
}
|
||||
|
||||
private void draw(App mApp) {
|
||||
app = mApp;
|
||||
actionButton = new ActionButton(this, app);
|
||||
disposable.add(Observable.just(
|
||||
new GeneralDetails(this, app),
|
||||
new Screenshot(this, app),
|
||||
new Reviews(this, app),
|
||||
new ExodusPrivacy(this, app),
|
||||
new Video(this, app),
|
||||
new Beta(this, app),
|
||||
new AppLinks(this, app))
|
||||
.zipWith(Observable.interval(16, TimeUnit.MILLISECONDS), (abstractHelper, interval) -> abstractHelper)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext(AbstractHelper::draw)
|
||||
.subscribe());
|
||||
drawButtons();
|
||||
}
|
||||
|
||||
public void drawButtons() {
|
||||
if (PackageUtil.isInstalled(context, app))
|
||||
app.setInstalled(true);
|
||||
if (actionButton != null)
|
||||
actionButton.draw();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> {
|
||||
fetchData();
|
||||
((Button) v).setText(getString(R.string.action_retry_ing));
|
||||
((Button) v).setEnabled(false);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errClose() {
|
||||
return v -> {
|
||||
if (getActivity() != null)
|
||||
getActivity().onBackPressed();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processException(Throwable e) {
|
||||
disposable.clear();
|
||||
if (e instanceof AppNotFoundException) {
|
||||
setErrorView(ErrorType.APP_NOT_FOUND);
|
||||
switchViews(true);
|
||||
} else
|
||||
super.processException(e);
|
||||
}
|
||||
|
||||
public IntentFilter getFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addDataScheme("package");
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_INSTALL);
|
||||
filter.addAction(Intent.ACTION_UNINSTALL_PACKAGE);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
filter.addAction(ACTION_PACKAGE_REPLACED_NON_SYSTEM);
|
||||
filter.addAction(ACTION_PACKAGE_INSTALLATION_FAILED);
|
||||
filter.addAction(ACTION_UNINSTALL_PACKAGE_FAILED);
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.EndlessScrollListener;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.adapter.EndlessAppsAdapter;
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.iterator.CustomAppListIterator;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.SearchTask;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.NetworkUtil;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.SearchIterator;
|
||||
import com.google.android.material.chip.Chip;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class DevAppsFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.search_apps_list)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.dev_name)
|
||||
Chip chipDevName;
|
||||
|
||||
private Context context;
|
||||
private String query;
|
||||
private EndlessAppsAdapter endlessAppsAdapter;
|
||||
private CustomAppListIterator iterator;
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
endlessAppsAdapter = new EndlessAppsAdapter(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_dev_applist, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
query = arguments.getString("SearchQuery");
|
||||
chipDevName.setText(arguments.getString("SearchTitle"));
|
||||
if (NetworkUtil.isConnected(context))
|
||||
setupRecycler();
|
||||
else
|
||||
notifyNetworkFailure();
|
||||
} else
|
||||
Log.e("No category id provided");
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setErrorView(ErrorType.UNKNOWN);
|
||||
fetchDevAppsList(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
fetchDevAppsList(true);
|
||||
}
|
||||
|
||||
private void fetchDevAppsList(boolean shouldIterate) {
|
||||
if (!shouldIterate)
|
||||
getIterator();
|
||||
disposable.add(Observable.fromCallable(() -> new SearchTask(context)
|
||||
.getSearchResults(iterator))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(appList -> {
|
||||
if (shouldIterate) {
|
||||
addApps(appList);
|
||||
} else if (appList.isEmpty()) {
|
||||
setErrorView(ErrorType.NO_SEARCH);
|
||||
switchViews(true);
|
||||
} else {
|
||||
switchViews(false);
|
||||
endlessAppsAdapter.addData(appList);
|
||||
}
|
||||
}, err -> {
|
||||
Log.e(err.getMessage());
|
||||
processException(err);
|
||||
}));
|
||||
}
|
||||
|
||||
private void getIterator() {
|
||||
try {
|
||||
GooglePlayAPI api = PlayStoreApiAuthenticator.getInstance(context);
|
||||
iterator = new CustomAppListIterator(new SearchIterator(api, query));
|
||||
} catch (Exception e) {
|
||||
processException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addApps(List<App> appsToAdd) {
|
||||
if (!appsToAdd.isEmpty()) {
|
||||
for (App app : appsToAdd)
|
||||
endlessAppsAdapter.add(app);
|
||||
endlessAppsAdapter.notifyItemInserted(endlessAppsAdapter.getItemCount() - 1);
|
||||
}
|
||||
if (iterator.hasNext() && endlessAppsAdapter.getItemCount() < 10) {
|
||||
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
fetchDevAppsList(true);
|
||||
cancel();
|
||||
}
|
||||
}, 2500, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRecycler() {
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false);
|
||||
recyclerView.setLayoutManager(mLayoutManager);
|
||||
recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(this.getActivity(), R.anim.anim_falldown));
|
||||
recyclerView.setAdapter(endlessAppsAdapter);
|
||||
EndlessScrollListener mScrollListener = new EndlessScrollListener(mLayoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
fetchDevAppsList(true);
|
||||
}
|
||||
};
|
||||
recyclerView.addOnScrollListener(mScrollListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> {
|
||||
if (NetworkUtil.isConnected(context)) {
|
||||
fetchDevAppsList(false);
|
||||
} else {
|
||||
setErrorView(ErrorType.NO_NETWORK);
|
||||
}
|
||||
((Button) v).setText(getString(R.string.action_retry_ing));
|
||||
((Button) v).setEnabled(false);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.SharedPreferencesTranslator;
|
||||
import com.aurora.store.adapter.FeaturedAppsAdapter;
|
||||
import com.aurora.store.adapter.TopCategoriesAdapter;
|
||||
import com.aurora.store.manager.CategoryManager;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.CategoryList;
|
||||
import com.aurora.store.task.FeaturedAppsTask;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class HomeFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.recycler_top_categories)
|
||||
RecyclerView recyclerTopCategories;
|
||||
@BindView(R.id.recycler_top_apps)
|
||||
RecyclerView recyclerTopApps;
|
||||
@BindView(R.id.recycler_top_games)
|
||||
RecyclerView recyclerTopGames;
|
||||
@BindView(R.id.recycler_top_family)
|
||||
RecyclerView recyclerTopFamily;
|
||||
|
||||
@BindView(R.id.btn_all_categories)
|
||||
MaterialButton btnAllCategories;
|
||||
@BindView(R.id.btn_top_apps)
|
||||
MaterialButton btnTopApps;
|
||||
@BindView(R.id.btn_top_games)
|
||||
MaterialButton btnTopGames;
|
||||
@BindView(R.id.btn_top_family)
|
||||
MaterialButton btnTopFamily;
|
||||
|
||||
private Context context;
|
||||
private FeaturedAppsAdapter topAppsAdapter;
|
||||
private FeaturedAppsAdapter topGamesAdapter;
|
||||
private FeaturedAppsAdapter topFamilyAdapter;
|
||||
private CategoryManager categoryManager;
|
||||
private FeaturedAppsTask featuredAppsTask;
|
||||
private SharedPreferencesTranslator translator;
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
featuredAppsTask = new FeaturedAppsTask(context);
|
||||
categoryManager = new CategoryManager(context);
|
||||
translator = new SharedPreferencesTranslator(Util.getPrefs(context));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_home, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setErrorView(ErrorType.UNKNOWN);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (topAppsAdapter.isDataEmpty())
|
||||
fetchTopAppsFromCache();
|
||||
if (topGamesAdapter.isDataEmpty())
|
||||
fetchTopGamesFromCache();
|
||||
if (topFamilyAdapter.isDataEmpty())
|
||||
fetchTopFamilyFromCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
disposable.clear();
|
||||
featuredAppsTask = null;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setupButtons();
|
||||
setupRecyclers();
|
||||
if (categoryManager.categoryListEmpty())
|
||||
getCategoriesFromAPI();
|
||||
}
|
||||
|
||||
private void setupButtons() {
|
||||
btnAllCategories.setOnClickListener(v -> getAllCategories());
|
||||
btnTopApps.setOnClickListener(v -> getCategoryApps("APPLICATION"));
|
||||
btnTopGames.setOnClickListener(v -> getCategoryApps("GAME"));
|
||||
btnTopFamily.setOnClickListener(v -> getCategoryApps("FAMILY"));
|
||||
}
|
||||
|
||||
private void setupRecyclers() {
|
||||
topAppsAdapter = new FeaturedAppsAdapter(context);
|
||||
topGamesAdapter = new FeaturedAppsAdapter(context);
|
||||
topFamilyAdapter = new FeaturedAppsAdapter(context);
|
||||
|
||||
recyclerTopCategories.setAdapter(new TopCategoriesAdapter(this));
|
||||
recyclerTopCategories.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
|
||||
recyclerTopApps.setAdapter(topAppsAdapter);
|
||||
recyclerTopApps.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
|
||||
recyclerTopGames.setAdapter(topGamesAdapter);
|
||||
recyclerTopGames.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
|
||||
recyclerTopFamily.setAdapter(topFamilyAdapter);
|
||||
recyclerTopFamily.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
|
||||
|
||||
Util.attachSnapPager(context, recyclerTopApps);
|
||||
Util.attachSnapPager(context, recyclerTopGames);
|
||||
Util.attachSnapPager(context, recyclerTopFamily);
|
||||
}
|
||||
|
||||
private void fetchTopApps() {
|
||||
disposable.add(Observable.fromCallable(() -> featuredAppsTask
|
||||
.getApps("APPLICATION", GooglePlayAPI.SUBCATEGORY.TOP_FREE))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((appList) -> {
|
||||
switchViews(false);
|
||||
topAppsAdapter.addData(appList);
|
||||
saveToCache(appList, Constants.PREFERENCE_TOP_APPS);
|
||||
Util.setCacheCreateTime(context, Calendar.getInstance().getTimeInMillis());
|
||||
}, err -> {
|
||||
processException(err);
|
||||
Log.d(err.getMessage());
|
||||
}));
|
||||
}
|
||||
|
||||
private void fetchTopGames() {
|
||||
disposable.add(Observable.fromCallable(() -> featuredAppsTask
|
||||
.getApps("GAME", GooglePlayAPI.SUBCATEGORY.TOP_GROSSING))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((appList) -> {
|
||||
switchViews(false);
|
||||
topGamesAdapter.addData(appList);
|
||||
saveToCache(appList, Constants.PREFERENCE_TOP_GAMES);
|
||||
}, err -> Log.d(err.getMessage())));
|
||||
}
|
||||
|
||||
private void fetchTopFamily() {
|
||||
disposable.add(Observable.fromCallable(() -> featuredAppsTask
|
||||
.getApps("FAMILY", GooglePlayAPI.SUBCATEGORY.TOP_GROSSING))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((appList) -> {
|
||||
switchViews(false);
|
||||
topFamilyAdapter.addData(appList);
|
||||
saveToCache(appList, Constants.PREFERENCE_TOP_FAMILY);
|
||||
}, err -> Log.d(err.getMessage())));
|
||||
}
|
||||
|
||||
private void saveToCache(List<App> appList, String key) {
|
||||
Gson gson = new Gson();
|
||||
String jsonString = gson.toJson(appList);
|
||||
PrefUtil.putString(context, key, jsonString);
|
||||
}
|
||||
|
||||
private void fetchTopAppsFromCache() {
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<List<App>>() {
|
||||
}.getType();
|
||||
String jsonString = PrefUtil.getString(context, Constants.PREFERENCE_TOP_APPS);
|
||||
List<App> appList = gson.fromJson(jsonString, type);
|
||||
if (appList == null || appList.isEmpty())
|
||||
fetchTopApps();
|
||||
else
|
||||
topAppsAdapter.addData(appList);
|
||||
}
|
||||
|
||||
private void fetchTopGamesFromCache() {
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<List<App>>() {
|
||||
}.getType();
|
||||
String jsonString = PrefUtil.getString(context, Constants.PREFERENCE_TOP_GAMES);
|
||||
List<App> appList = gson.fromJson(jsonString, type);
|
||||
if (appList == null || appList.isEmpty())
|
||||
fetchTopGames();
|
||||
else
|
||||
topGamesAdapter.addData(appList);
|
||||
}
|
||||
|
||||
private void fetchTopFamilyFromCache() {
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<List<App>>() {
|
||||
}.getType();
|
||||
String jsonString = PrefUtil.getString(context, Constants.PREFERENCE_TOP_FAMILY);
|
||||
List<App> appList = gson.fromJson(jsonString, type);
|
||||
if (appList == null || appList.isEmpty())
|
||||
fetchTopFamily();
|
||||
else
|
||||
topFamilyAdapter.addData(appList);
|
||||
}
|
||||
|
||||
private void getAllCategories() {
|
||||
CategoriesFragment categoryAppsFragment = new CategoriesFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("CATEGORY_TYPE", "APPLICATION");
|
||||
categoryAppsFragment.setArguments(arguments);
|
||||
getChildFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.coordinator, categoryAppsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void getCategoryApps(String categoryID) {
|
||||
CategoryAppsFragment categoryAppsFragment = new CategoryAppsFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("CategoryId", categoryID);
|
||||
arguments.putString("CategoryName", translator.getString(categoryID));
|
||||
categoryAppsFragment.setArguments(arguments);
|
||||
getChildFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.coordinator, categoryAppsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void getCategoriesFromAPI() {
|
||||
disposable.add(Observable.fromCallable(() -> new CategoryList(getContext())
|
||||
.getResult())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(success -> {
|
||||
}, err -> Log.e(err.getMessage())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> {
|
||||
fetchTopApps();
|
||||
fetchTopGames();
|
||||
fetchTopFamily();
|
||||
((Button) v).setText(getString(R.string.action_retry_ing));
|
||||
((Button) v).setEnabled(false);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
ContextUtil.runOnUiThread(() -> {
|
||||
fetchTopApps();
|
||||
fetchTopGames();
|
||||
fetchTopFamily();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.ListType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.adapter.InstalledAppsAdapter;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.InstalledAppsTask;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.view.CustomSwipeToRefresh;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class InstalledFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.swipe_layout)
|
||||
CustomSwipeToRefresh customSwipeToRefresh;
|
||||
@BindView(R.id.recycler)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.switch_system)
|
||||
SwitchMaterial switchSystem;
|
||||
|
||||
private Context context;
|
||||
private View view;
|
||||
private InstalledAppsAdapter adapter;
|
||||
private InstalledAppsTask installedAppTask;
|
||||
|
||||
@Override
|
||||
public void onAttach(@NotNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
view = inflater.inflate(R.layout.fragment_installed, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setErrorView(ErrorType.UNKNOWN);
|
||||
|
||||
switchSystem.setChecked(PrefUtil.getBoolean(context, Constants.PREFERENCE_INCLUDE_SYSTEM));
|
||||
switchSystem.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
if (isChecked)
|
||||
PrefUtil.putBoolean(context, Constants.PREFERENCE_INCLUDE_SYSTEM, true);
|
||||
else
|
||||
PrefUtil.putBoolean(context, Constants.PREFERENCE_INCLUDE_SYSTEM, false);
|
||||
fetchData();
|
||||
});
|
||||
customSwipeToRefresh.setOnRefreshListener(() -> fetchData());
|
||||
setupRecycler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
customSwipeToRefresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (adapter.isDataEmpty())
|
||||
fetchAppsFromCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
installedAppTask = null;
|
||||
adapter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
installedAppTask = new InstalledAppsTask(context);
|
||||
disposable.add(Observable.fromCallable(() -> installedAppTask
|
||||
.getInstalledApps(switchSystem.isChecked()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnSubscribe(subscription -> customSwipeToRefresh.setRefreshing(true))
|
||||
.doOnTerminate(() -> customSwipeToRefresh.setRefreshing(false))
|
||||
.subscribe((appList) -> {
|
||||
if (view != null) {
|
||||
if (appList.isEmpty()) {
|
||||
setErrorView(ErrorType.NO_APPS);
|
||||
switchViews(true);
|
||||
} else {
|
||||
switchViews(false);
|
||||
if (adapter != null)
|
||||
adapter.addData(appList);
|
||||
saveToCache(appList);
|
||||
}
|
||||
}
|
||||
}, err -> {
|
||||
Log.d(err.getMessage());
|
||||
processException(err);
|
||||
}));
|
||||
}
|
||||
|
||||
private void saveToCache(List<App> appList) {
|
||||
Gson gson = new Gson();
|
||||
String jsonString = gson.toJson(appList);
|
||||
PrefUtil.putString(context, Constants.PREFERENCE_INSTALLED_APPS, jsonString);
|
||||
}
|
||||
|
||||
private void fetchAppsFromCache() {
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<List<App>>() {
|
||||
}.getType();
|
||||
String jsonString = PrefUtil.getString(context, Constants.PREFERENCE_INSTALLED_APPS);
|
||||
List<App> appList = gson.fromJson(jsonString, type);
|
||||
if (appList == null || appList.isEmpty())
|
||||
fetchData();
|
||||
else {
|
||||
adapter.addData(appList);
|
||||
switchViews(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRecycler() {
|
||||
adapter = new InstalledAppsAdapter(context, ListType.INSTALLED);
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
|
||||
recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(context, R.anim.anim_falldown));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> {
|
||||
fetchData();
|
||||
((Button) v).setText(getString(R.string.action_retry_ing));
|
||||
((Button) v).setEnabled(false);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.EndlessScrollListener;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.Filter;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.adapter.EndlessAppsAdapter;
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.iterator.CustomAppListIterator;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.sheet.FilterBottomSheet;
|
||||
import com.aurora.store.task.SearchTask;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.NetworkUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.SearchIterator;
|
||||
import com.google.android.material.chip.Chip;
|
||||
import com.google.android.material.chip.ChipGroup;
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class SearchAppsFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.search_apps)
|
||||
SearchView searchView;
|
||||
@BindView(R.id.search_apps_list)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.filter_fab)
|
||||
ExtendedFloatingActionButton filterFab;
|
||||
@BindView(R.id.related_chip_group)
|
||||
ChipGroup relatedChipGroup;
|
||||
|
||||
private Context context;
|
||||
private String query;
|
||||
private List<String> relatedTags = new ArrayList<>();
|
||||
private CustomAppListIterator iterator;
|
||||
private EndlessAppsAdapter endlessAppsAdapter;
|
||||
|
||||
private String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
private void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
endlessAppsAdapter = new EndlessAppsAdapter(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_search_applist, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
setQuery(arguments.getString("SearchQuery"));
|
||||
searchView.setQuery(getQuery(), false);
|
||||
} else
|
||||
Log.e("No category id provided");
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setErrorView(ErrorType.UNKNOWN);
|
||||
if (!NetworkUtil.isConnected(context)) {
|
||||
setErrorView(ErrorType.NO_NETWORK);
|
||||
switchViews(true);
|
||||
}
|
||||
setupRecycler();
|
||||
setupSearch();
|
||||
filterFab.show();
|
||||
filterFab.setOnClickListener(v -> getFilterDialog());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
fetchSearchAppsList(false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Glide.with(this).pauseAllRequests();
|
||||
disposable.dispose();
|
||||
if (Util.filterSearchNonPersistent(context))
|
||||
new Filter(context).resetFilterPreferences();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void setupSearch() {
|
||||
SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
|
||||
ComponentName componentName = getActivity().getComponentName();
|
||||
|
||||
if (null != searchManager && componentName != null) {
|
||||
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName));
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(AuroraActivity.externalQuery))
|
||||
setQuery(AuroraActivity.externalQuery);
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextChange(String query) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String newQuery) {
|
||||
searchView.clearFocus();
|
||||
query = newQuery;
|
||||
fetchSearchAppsList(false);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
|
||||
@Override
|
||||
public boolean onSuggestionSelect(int position) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSuggestionClick(int position) {
|
||||
Cursor cursor = searchView.getSuggestionsAdapter().getCursor();
|
||||
cursor.moveToPosition(position);
|
||||
if (position == 0) {
|
||||
searchView.setQuery(cursor.getString(2), true);
|
||||
searchView.setQuery(cursor.getString(1), false);
|
||||
} else
|
||||
searchView.setQuery(cursor.getString(1), true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getFilterDialog() {
|
||||
FilterBottomSheet filterSheet = new FilterBottomSheet();
|
||||
filterSheet.setCancelable(true);
|
||||
filterSheet.setOnApplyListener(v -> {
|
||||
filterSheet.dismiss();
|
||||
recyclerView.removeAllViewsInLayout();
|
||||
fetchSearchAppsList(false);
|
||||
});
|
||||
filterSheet.show(getChildFragmentManager(), "FILTER");
|
||||
}
|
||||
|
||||
private void getIterator() {
|
||||
try {
|
||||
GooglePlayAPI api = PlayStoreApiAuthenticator.getInstance(context);
|
||||
iterator = new CustomAppListIterator(new SearchIterator(api, query));
|
||||
iterator.setFilterEnabled(true);
|
||||
iterator.setFilter(new Filter(getContext()).getFilterPreferences());
|
||||
relatedTags = iterator.getRelatedTags();
|
||||
} catch (Exception e) {
|
||||
Log.e("BAZINGA");
|
||||
processException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchSearchAppsList(boolean shouldIterate) {
|
||||
if (!shouldIterate)
|
||||
getIterator();
|
||||
disposable.add(Observable.fromCallable(() -> new SearchTask(context)
|
||||
.getSearchResults(iterator))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(appList -> {
|
||||
if (shouldIterate) {
|
||||
addApps(appList);
|
||||
} else if (appList.isEmpty() && endlessAppsAdapter.isDataEmpty()) {
|
||||
setErrorView(ErrorType.NO_SEARCH);
|
||||
switchViews(true);
|
||||
filterFab.hide();
|
||||
} else {
|
||||
switchViews(false);
|
||||
filterFab.show();
|
||||
if (endlessAppsAdapter != null)
|
||||
endlessAppsAdapter.addData(appList);
|
||||
if (!relatedTags.isEmpty())
|
||||
setupTags();
|
||||
}
|
||||
}, err -> {
|
||||
filterFab.hide();
|
||||
processException(err);
|
||||
}));
|
||||
}
|
||||
|
||||
private void addApps(List<App> appsToAdd) {
|
||||
if (!appsToAdd.isEmpty()) {
|
||||
for (App app : appsToAdd)
|
||||
endlessAppsAdapter.add(app);
|
||||
endlessAppsAdapter.notifyItemInserted(endlessAppsAdapter.getItemCount() - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search results are scarce if filter are too strict, in this case endless scroll events
|
||||
* fail to fetch next batch of apps, so manually fetch at least 10 apps until available.
|
||||
*/
|
||||
disposable.add(Observable.interval(1000, 2000, TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> {
|
||||
if (iterator.hasNext() && endlessAppsAdapter.getItemCount() < 10) {
|
||||
iterator.next();
|
||||
}
|
||||
}, e -> Log.e(e.getMessage())));
|
||||
}
|
||||
|
||||
private void setupRecycler() {
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(context, RecyclerView.VERTICAL, false);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(this.getActivity(), R.anim.anim_falldown));
|
||||
recyclerView.setAdapter(endlessAppsAdapter);
|
||||
EndlessScrollListener endlessScrollListener = new EndlessScrollListener(layoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
fetchSearchAppsList(true);
|
||||
}
|
||||
};
|
||||
recyclerView.addOnScrollListener(endlessScrollListener);
|
||||
recyclerView.setOnFlingListener(new RecyclerView.OnFlingListener() {
|
||||
@Override
|
||||
public boolean onFling(int velocityX, int velocityY) {
|
||||
if (velocityY < 0) {
|
||||
filterFab.show();
|
||||
} else if (velocityY > 0) {
|
||||
filterFab.hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupTags() {
|
||||
relatedChipGroup.removeAllViews();
|
||||
int i = 0;
|
||||
for (String tag : relatedTags) {
|
||||
final int color = ViewUtil.getSolidColors(i++);
|
||||
Chip chip = new Chip(context);
|
||||
chip.setText(tag);
|
||||
chip.setChipIconSize(ViewUtil.dpToPx(context, 24));
|
||||
chip.setChipStrokeWidth(ViewUtil.dpToPx(context, 1));
|
||||
chip.setChipStrokeColor(ColorStateList.valueOf(color));
|
||||
chip.setChipBackgroundColor(ColorStateList.valueOf(ColorUtils.setAlphaComponent(color, 100)));
|
||||
chip.setRippleColor(ColorStateList.valueOf(ColorUtils.setAlphaComponent(color, 200)));
|
||||
chip.setCheckedIcon(context.getDrawable(R.drawable.ic_checked));
|
||||
chip.setOnClickListener(v -> {
|
||||
if (chip.isChecked()) {
|
||||
query = query + " " + tag;
|
||||
fetchData();
|
||||
searchView.setQuery(query, false);
|
||||
} else {
|
||||
query = query.replace(tag, "");
|
||||
fetchData();
|
||||
searchView.setQuery(query, false);
|
||||
}
|
||||
});
|
||||
relatedChipGroup.addView(chip);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
fetchSearchAppsList(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> {
|
||||
if (NetworkUtil.isConnected(context)) {
|
||||
fetchData();
|
||||
} else {
|
||||
setErrorView(ErrorType.NO_NETWORK);
|
||||
}
|
||||
((Button) v).setText(getString(R.string.action_retry_ing));
|
||||
((Button) v).setEnabled(false);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.HistoryItemTouchHelper;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.adapter.SearchHistoryAdapter;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class SearchFragment extends Fragment implements HistoryItemTouchHelper.RecyclerItemTouchHelperListener, SearchHistoryAdapter.ClickListener {
|
||||
|
||||
@BindView(R.id.search_apps)
|
||||
SearchView searchView;
|
||||
@BindView(R.id.searchHistory)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.emptyView)
|
||||
TextView emptyView;
|
||||
@BindView(R.id.clearAll)
|
||||
Button clearAll;
|
||||
|
||||
private Context context;
|
||||
private ArrayList<String> queryList;
|
||||
private SearchHistoryAdapter searchHistoryAdapter;
|
||||
|
||||
@Override
|
||||
public void onAttach(@NotNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
View view = inflater.inflate(R.layout.fragment_search, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setupSearch();
|
||||
setupHistory();
|
||||
clearAll.setOnClickListener(v -> clearAll());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (searchView != null && Util.isIMEEnabled(context))
|
||||
searchView.requestFocus();
|
||||
}
|
||||
|
||||
private void setupSearch() {
|
||||
SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
|
||||
ComponentName componentName = getActivity().getComponentName();
|
||||
|
||||
if (null != searchManager && componentName != null) {
|
||||
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName));
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(AuroraActivity.externalQuery))
|
||||
setQuery(AuroraActivity.externalQuery);
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextChange(String query) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
searchView.clearFocus();
|
||||
setQuery(query);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
|
||||
@Override
|
||||
public boolean onSuggestionSelect(int position) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSuggestionClick(int position) {
|
||||
Cursor cursor = searchView.getSuggestionsAdapter().getCursor();
|
||||
cursor.moveToPosition(position);
|
||||
if (position == 0) {
|
||||
searchView.setQuery(cursor.getString(2), true);
|
||||
searchView.setQuery(cursor.getString(1), false);
|
||||
saveQuery(cursor.getString(1));
|
||||
} else
|
||||
searchView.setQuery(cursor.getString(1), true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setQuery(String query) {
|
||||
if (Util.isSearchByPackageEnabled(context) && looksLikeAPackageId(query)) {
|
||||
context.startActivity(DetailsActivity.getDetailsIntent(getContext(), query));
|
||||
} else {
|
||||
getQueriedApps(query);
|
||||
saveQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveQuery(String query) {
|
||||
String mDatedQuery = query + ":" + Calendar.getInstance().getTimeInMillis();
|
||||
setQueryToPref(mDatedQuery);
|
||||
}
|
||||
|
||||
private void setQueryToPref(String query) {
|
||||
queryList = PrefUtil.getListString(context, Constants.RECENT_HISTORY);
|
||||
queryList.add(0, query);
|
||||
PrefUtil.putListString(context, Constants.RECENT_HISTORY, queryList);
|
||||
if (searchHistoryAdapter != null)
|
||||
searchHistoryAdapter.reload();
|
||||
else
|
||||
setupSearchHistory(queryList);
|
||||
}
|
||||
|
||||
private void setupHistory() {
|
||||
queryList = PrefUtil.getListString(context, Constants.RECENT_HISTORY);
|
||||
if (!queryList.isEmpty()) {
|
||||
setupSearchHistory(queryList);
|
||||
toggleViews(false);
|
||||
} else {
|
||||
toggleViews(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupSearchHistory(ArrayList<String> historyList) {
|
||||
searchHistoryAdapter = new SearchHistoryAdapter(context, historyList, this);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
recyclerView.setAdapter(searchHistoryAdapter);
|
||||
new ItemTouchHelper(
|
||||
new HistoryItemTouchHelper(0, ItemTouchHelper.LEFT, this))
|
||||
.attachToRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
private void clearAll() {
|
||||
if (searchHistoryAdapter != null)
|
||||
searchHistoryAdapter.clear();
|
||||
toggleViews(true);
|
||||
}
|
||||
|
||||
private void toggleViews(Boolean shouldHide) {
|
||||
if (shouldHide) {
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
emptyView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) {
|
||||
if (viewHolder instanceof SearchHistoryAdapter.ViewHolder) {
|
||||
searchHistoryAdapter.remove(position);
|
||||
if (searchHistoryAdapter.getItemCount() < 1)
|
||||
clearAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void getQueriedApps(String query) {
|
||||
if (searchView != null)
|
||||
searchView.setQuery("", false);
|
||||
SearchAppsFragment searchAppsFragment = new SearchAppsFragment();
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString("SearchQuery", query);
|
||||
arguments.putString("SearchTitle", getTitleString(query));
|
||||
searchAppsFragment.setArguments(arguments);
|
||||
getChildFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.coordinator, searchAppsFragment)
|
||||
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private String getTitleString(String query) {
|
||||
return query.startsWith(Constants.PUB_PREFIX)
|
||||
? getString(R.string.apps_by, query.substring(Constants.PUB_PREFIX.length()))
|
||||
: getString(R.string.title_search_result, query)
|
||||
;
|
||||
}
|
||||
|
||||
private boolean looksLikeAPackageId(String query) {
|
||||
if (TextUtils.isEmpty(query)) {
|
||||
return false;
|
||||
}
|
||||
String pattern = "([\\p{L}_$][\\p{L}\\p{N}_$]*\\.)+[\\p{L}_$][\\p{L}\\p{N}_$]*";
|
||||
Pattern r = Pattern.compile(pattern);
|
||||
return r.matcher(query).matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClicked(String query) {
|
||||
getQueriedApps(query);
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.EndlessScrollListener;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.Filter;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.adapter.EndlessAppsAdapter;
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.iterator.CustomAppListIterator;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.CategoryAppsTask;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.dragons.aurora.playstoreapiv2.CategoryAppsIterator;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.IteratorGooglePlayException;
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class SubCategoryFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.endless_apps_list)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
private Context context;
|
||||
private CustomAppListIterator iterator;
|
||||
private GooglePlayAPI.SUBCATEGORY subcategory = GooglePlayAPI.SUBCATEGORY.TOP_FREE;
|
||||
private ExtendedFloatingActionButton filterFab;
|
||||
private EndlessAppsAdapter endlessAppsAdapter;
|
||||
|
||||
private GooglePlayAPI.SUBCATEGORY getSubcategory() {
|
||||
return subcategory;
|
||||
}
|
||||
|
||||
private void setSubcategory(Bundle bundle) {
|
||||
String category = bundle.getString("SUBCATEGORY");
|
||||
if (category != null)
|
||||
switch (category) {
|
||||
case "TOP_FREE":
|
||||
subcategory = GooglePlayAPI.SUBCATEGORY.TOP_FREE;
|
||||
break;
|
||||
case "TOP_GROSSING":
|
||||
subcategory = GooglePlayAPI.SUBCATEGORY.TOP_GROSSING;
|
||||
break;
|
||||
default:
|
||||
subcategory = GooglePlayAPI.SUBCATEGORY.MOVERS_SHAKERS;
|
||||
}
|
||||
}
|
||||
|
||||
private CustomAppListIterator getIterator() {
|
||||
return iterator;
|
||||
}
|
||||
|
||||
private void setIterator(CustomAppListIterator iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
endlessAppsAdapter = new EndlessAppsAdapter(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_category_applist, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null)
|
||||
setSubcategory(bundle);
|
||||
initIterator();
|
||||
setupRecycler();
|
||||
|
||||
if (getParentFragment() != null && getParentFragment() instanceof CategoryAppsFragment) {
|
||||
filterFab = ((CategoryAppsFragment) getParentFragment()).getFilterFab();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (endlessAppsAdapter.isDataEmpty())
|
||||
fetchCategoryApps(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
disposable.clear();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void initIterator() {
|
||||
iterator = setupIterator(CategoryAppsFragment.categoryId, getSubcategory());
|
||||
if (iterator != null) {
|
||||
iterator.setFilter(new Filter(getContext()).getFilterPreferences());
|
||||
iterator.setFilterEnabled(true);
|
||||
setIterator(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRecycler() {
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(context, RecyclerView.VERTICAL, false);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setAdapter(endlessAppsAdapter);
|
||||
EndlessScrollListener mEndlessRecyclerViewScrollListener = new EndlessScrollListener(layoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
fetchCategoryApps(true);
|
||||
}
|
||||
};
|
||||
recyclerView.addOnScrollListener(mEndlessRecyclerViewScrollListener);
|
||||
recyclerView.setOnFlingListener(new RecyclerView.OnFlingListener() {
|
||||
@Override
|
||||
public boolean onFling(int velocityX, int velocityY) {
|
||||
if (velocityY < 0) {
|
||||
filterFab.show();
|
||||
} else if (velocityY > 0) {
|
||||
filterFab.hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private CustomAppListIterator setupIterator(String categoryId, GooglePlayAPI.SUBCATEGORY subcategory) {
|
||||
try {
|
||||
final GooglePlayAPI api = PlayStoreApiAuthenticator.getInstance(context);
|
||||
final CategoryAppsIterator iterator = new CategoryAppsIterator(api, categoryId, subcategory);
|
||||
return new CustomAppListIterator(iterator);
|
||||
} catch (Exception err) {
|
||||
processException(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchCategoryApps(boolean shouldIterate) {
|
||||
disposable.add(Observable.fromCallable(() -> new CategoryAppsTask(getContext())
|
||||
.getApps(getIterator()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(appList -> {
|
||||
if (appList.isEmpty() && endlessAppsAdapter.isDataEmpty()) {
|
||||
setErrorView(ErrorType.NO_APPS);
|
||||
switchViews(true);
|
||||
} else {
|
||||
switchViews(false);
|
||||
if (shouldIterate) {
|
||||
addApps(appList);
|
||||
} else
|
||||
endlessAppsAdapter.addData(appList);
|
||||
}
|
||||
}, err -> {
|
||||
if (err instanceof IteratorGooglePlayException)
|
||||
processException(err.getCause());
|
||||
else
|
||||
processException(err);
|
||||
}));
|
||||
}
|
||||
|
||||
private void addApps(List<App> appsToAdd) {
|
||||
if (!appsToAdd.isEmpty()) {
|
||||
for (App app : appsToAdd)
|
||||
endlessAppsAdapter.add(app);
|
||||
endlessAppsAdapter.notifyItemInserted(endlessAppsAdapter.getItemCount() - 1);
|
||||
}
|
||||
disposable.add(Observable.interval(1000, 2000, TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> {
|
||||
if (iterator.hasNext() && endlessAppsAdapter.getItemCount() < 10) {
|
||||
iterator.next();
|
||||
}
|
||||
}, e -> Log.e(e.getMessage())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> ContextUtil.runOnUiThread(() -> fetchCategoryApps(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
fetchCategoryApps(false);
|
||||
}
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.AuroraApplication;
|
||||
import com.aurora.store.ErrorType;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.adapter.UpdatableAppsAdapter;
|
||||
import com.aurora.store.download.DownloadManager;
|
||||
import com.aurora.store.exception.MalformedRequestException;
|
||||
import com.aurora.store.exception.NotPurchasedException;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.LiveUpdate;
|
||||
import com.aurora.store.task.ObservableDeliveryData;
|
||||
import com.aurora.store.task.UpdatableAppsTask;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.utility.ViewUtil;
|
||||
import com.aurora.store.view.CustomSwipeToRefresh;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.tonyodev.fetch2.Fetch;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
public class UpdatesFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.swipe_layout)
|
||||
CustomSwipeToRefresh customSwipeToRefresh;
|
||||
@BindView(R.id.recycler)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.btn_action)
|
||||
Button btnAction;
|
||||
@BindView(R.id.txt_update_all)
|
||||
TextView txtUpdateAll;
|
||||
|
||||
private Context context;
|
||||
private List<App> updatableAppList = new ArrayList<>();
|
||||
private UpdatableAppsAdapter adapter;
|
||||
private Fetch fetch;
|
||||
private UpdatableAppsTask updatableAppTask;
|
||||
private BottomNavigationView bottomNavigationView;
|
||||
|
||||
private BroadcastReceiver installReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String packageName = intent.getStringExtra("PACKAGE_NAME");
|
||||
try {
|
||||
removeInstalledApp(packageName);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onAttach(@NotNull Context context) {
|
||||
super.onAttach(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_updates, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
fetch = DownloadManager.getFetchInstance(context);
|
||||
adapter = new UpdatableAppsAdapter(context);
|
||||
updatableAppTask = new UpdatableAppsTask(context);
|
||||
setErrorView(ErrorType.UNKNOWN);
|
||||
customSwipeToRefresh.setOnRefreshListener(() -> fetchData());
|
||||
setupRecycler();
|
||||
|
||||
if (getActivity() instanceof AuroraActivity) {
|
||||
bottomNavigationView = ((AuroraActivity) getActivity()).getBottomNavigation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
context.registerReceiver(installReceiver, new IntentFilter("ACTION_INSTALL"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (adapter.isDataEmpty()) {
|
||||
fetchData();
|
||||
drawButtons();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
customSwipeToRefresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
try {
|
||||
context.unregisterReceiver(installReceiver);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fetchData() {
|
||||
disposable.add(Observable.fromCallable(updatableAppTask::getUpdatableApps)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnSubscribe(subscription -> customSwipeToRefresh.setRefreshing(true))
|
||||
.doOnTerminate(() -> customSwipeToRefresh.setRefreshing(false))
|
||||
.subscribe((appList) -> {
|
||||
updatableAppList = appList;
|
||||
if (appList.isEmpty()) {
|
||||
setErrorView(ErrorType.NO_UPDATES);
|
||||
switchViews(true);
|
||||
} else {
|
||||
switchViews(false);
|
||||
if (adapter != null)
|
||||
adapter.addData(appList);
|
||||
drawButtons();
|
||||
updateCounter();
|
||||
}
|
||||
}, err -> {
|
||||
Log.d(err.getMessage());
|
||||
processException(err);
|
||||
}));
|
||||
}
|
||||
|
||||
private void removeInstalledApp(String packageName) {
|
||||
adapter.remove(packageName);
|
||||
AuroraApplication.removeFromOngoingUpdateList(packageName);
|
||||
drawButtons();
|
||||
updateCounter();
|
||||
}
|
||||
|
||||
private void setupRecycler() {
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
|
||||
recyclerView.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(context, R.anim.anim_falldown));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener errRetry() {
|
||||
return v -> {
|
||||
fetchData();
|
||||
if (updatableAppList != null) {
|
||||
((Button) v).setText(updatableAppList.isEmpty()
|
||||
? getString(R.string.action_recheck_ing)
|
||||
: getString(R.string.action_retry_ing));
|
||||
((Button) v).setEnabled(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void drawButtons() {
|
||||
btnAction.setEnabled(true);
|
||||
if (updatableAppList != null && updatableAppList.isEmpty()) {
|
||||
ViewUtil.hideWithAnimation(btnAction);
|
||||
txtUpdateAll.setText(context.getString(R.string.list_empty_updates));
|
||||
setErrorView(ErrorType.NO_UPDATES);
|
||||
} else if (AuroraApplication.getOnGoingUpdate()) {
|
||||
btnAction.setOnClickListener(cancelAllListener());
|
||||
} else {
|
||||
btnAction.setOnClickListener(updateAllListener());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCounter() {
|
||||
int count = adapter.getItemCount();
|
||||
txtUpdateAll.setText(new StringBuilder()
|
||||
.append(adapter.getItemCount())
|
||||
.append(StringUtils.SPACE)
|
||||
.append(count == 1 ? context.getString(R.string.list_update_all_txt_one) :
|
||||
context.getString(R.string.list_update_all_txt)));
|
||||
}
|
||||
|
||||
private View.OnClickListener updateAllListener() {
|
||||
ViewUtil.showWithAnimation(btnAction);
|
||||
btnAction.setText(getString(R.string.list_update_all));
|
||||
return v -> {
|
||||
updateAllApps();
|
||||
btnAction.setText(getString(R.string.list_updating));
|
||||
btnAction.setEnabled(false);
|
||||
};
|
||||
}
|
||||
|
||||
private View.OnClickListener cancelAllListener() {
|
||||
ViewUtil.showWithAnimation(btnAction);
|
||||
btnAction.setText(getString(R.string.action_cancel));
|
||||
return v -> {
|
||||
cancelAllRequests();
|
||||
AuroraApplication.setOngoingUpdateList(new ArrayList<>());
|
||||
AuroraApplication.setOnGoingUpdate(false);
|
||||
Util.clearOldInstallationSessions(context);
|
||||
ContextUtil.runOnUiThread(() -> drawButtons());
|
||||
};
|
||||
}
|
||||
|
||||
private void updateAllApps() {
|
||||
AuroraApplication.setOngoingUpdateList(updatableAppList);
|
||||
AuroraApplication.setOnGoingUpdate(true);
|
||||
disposable.add(Observable.fromIterable(updatableAppList)
|
||||
.flatMap(app -> new ObservableDeliveryData(context).getDeliveryData(app))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.doOnSubscribe(disposable -> drawButtons())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext(deliveryDataBundle -> new LiveUpdate(context)
|
||||
.enqueueUpdate(deliveryDataBundle.getApp(),
|
||||
deliveryDataBundle.getAndroidAppDeliveryData()))
|
||||
.doOnError(throwable -> {
|
||||
if (throwable instanceof MalformedRequestException || throwable instanceof NotPurchasedException) {
|
||||
ContextUtil.runOnUiThread(() -> btnAction.setOnClickListener(updateAllListener()));
|
||||
notifyStatusBlacklist(coordinatorLayout, throwable.getMessage());
|
||||
} else
|
||||
Log.e(throwable.getMessage());
|
||||
})
|
||||
.subscribe());
|
||||
}
|
||||
|
||||
private void cancelAllRequests() {
|
||||
List<App> ongoingUpdateList = AuroraApplication.getOngoingUpdateList();
|
||||
for (App app : ongoingUpdateList) {
|
||||
Log.i("Cancelled -> %s", app.getDisplayName());
|
||||
fetch.cancelGroup(app.getPackageName().hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyStatusBlacklist(CoordinatorLayout coordinatorLayout, String packageName) {
|
||||
final StringBuilder message = new StringBuilder()
|
||||
.append(packageName)
|
||||
.append(StringUtils.SPACE)
|
||||
.append(context.getString(R.string.error_app_download));
|
||||
Snackbar snackbar = Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG);
|
||||
if (bottomNavigationView != null)
|
||||
snackbar.setAnchorView(bottomNavigationView);
|
||||
snackbar.show();
|
||||
}
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment.details;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.fragment.DetailsFragment;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.task.BaseTask;
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class Beta extends AbstractHelper {
|
||||
|
||||
@BindView(R.id.beta_comment)
|
||||
EditText editText;
|
||||
@BindView(R.id.beta_layout)
|
||||
RelativeLayout beta_card;
|
||||
@BindView(R.id.beta_feedback)
|
||||
LinearLayout beta_feedback;
|
||||
@BindView(R.id.beta_message)
|
||||
TextView txt_beta_message;
|
||||
@BindView(R.id.beta_subscribe_button)
|
||||
Button beta_subscribe_button;
|
||||
@BindView(R.id.beta_submit_button)
|
||||
Button beta_submit_button;
|
||||
@BindView(R.id.beta_delete_button)
|
||||
Button beta_delete_button;
|
||||
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
public Beta(DetailsFragment fragment, App app) {
|
||||
super(fragment, app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
ButterKnife.bind(this, view);
|
||||
if (Accountant.isAnonymous(context))
|
||||
return;
|
||||
|
||||
if (app.isTestingProgramAvailable() && app.isTestingProgramOptedIn()) {
|
||||
disposable.add(Observable.fromCallable(() -> new BetaFeedbackToggleTask(context)
|
||||
.toggle(app))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe());
|
||||
}
|
||||
|
||||
if (!app.isInstalled() || !app.isTestingProgramAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setText(view, R.id.beta_header, app.isTestingProgramOptedIn()
|
||||
? R.string.testing_program_section_opted_in_title
|
||||
: R.string.testing_program_section_opted_out_title);
|
||||
|
||||
setText(view, R.id.beta_message, app.isTestingProgramOptedIn()
|
||||
? R.string.testing_program_section_opted_in_message
|
||||
: R.string.testing_program_section_opted_out_message);
|
||||
|
||||
setText(view, R.id.beta_subscribe_button, app.isTestingProgramOptedIn()
|
||||
? R.string.testing_program_opt_out
|
||||
: R.string.testing_program_opt_in);
|
||||
|
||||
setText(fragment.getView(), R.id.beta_email, app.getTestingProgramEmail());
|
||||
|
||||
beta_card.setVisibility(View.VISIBLE);
|
||||
beta_feedback.setVisibility(app.isTestingProgramOptedIn() ? View.VISIBLE : View.GONE);
|
||||
beta_subscribe_button.setOnClickListener(new BetaOnClickListener(txt_beta_message, app));
|
||||
beta_submit_button.setOnClickListener(v -> disposable.add(Observable.fromCallable(() ->
|
||||
new BetaFeedbackSubmitTask(context).deleteFeedback(app.getPackageName(), editText.getText().toString()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((success) -> {
|
||||
beta_delete_button.setVisibility(View.VISIBLE);
|
||||
beta_delete_button.setEnabled(true);
|
||||
})));
|
||||
beta_delete_button.setOnClickListener(v -> disposable.add(Observable.fromCallable(() ->
|
||||
new BetaFeedbackDeleteTask(context).deleteFeedback(app.getPackageName()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((success) -> {
|
||||
editText.setText("");
|
||||
ContextUtil.toastShort(context, context.getString(R.string.action_done));
|
||||
beta_delete_button.setEnabled(false);
|
||||
})));
|
||||
|
||||
if (null != app.getUserReview() && !TextUtils.isEmpty(app.getUserReview().getComment())) {
|
||||
editText.setText(app.getUserReview().getComment());
|
||||
show(view, R.id.beta_delete_button);
|
||||
}
|
||||
}
|
||||
|
||||
static private class BetaOnClickListener implements View.OnClickListener {
|
||||
|
||||
private TextView messageView;
|
||||
private App app;
|
||||
private CompositeDisposable mDisposable = new CompositeDisposable();
|
||||
|
||||
private BetaOnClickListener(TextView messageView, App app) {
|
||||
this.messageView = messageView;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
view.setEnabled(false);
|
||||
messageView.setText(app.isTestingProgramOptedIn()
|
||||
? R.string.testing_program_section_opted_out_propagating_message
|
||||
: R.string.testing_program_section_opted_in_propagating_message);
|
||||
mDisposable.add(Observable.fromCallable(() -> new BetaFeedbackToggleTask(messageView.getContext()).toggle(app))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe());
|
||||
mDisposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static private class BetaFeedbackToggleTask extends BaseTask {
|
||||
|
||||
BetaFeedbackToggleTask(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private boolean toggle(App app) throws Exception {
|
||||
try {
|
||||
GooglePlayAPI api = getApi();
|
||||
api.testingProgram(app.getPackageName(), !app.isTestingProgramOptedIn());
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private class BetaFeedbackSubmitTask extends BaseTask {
|
||||
|
||||
BetaFeedbackSubmitTask(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private boolean deleteFeedback(String packageName, String feedback) {
|
||||
try {
|
||||
GooglePlayAPI api = getApi();
|
||||
api.betaFeedback(packageName, feedback);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private class BetaFeedbackDeleteTask extends BaseTask {
|
||||
|
||||
BetaFeedbackDeleteTask(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private boolean deleteFeedback(String packageName) {
|
||||
try {
|
||||
GooglePlayAPI api = getApi();
|
||||
api.deleteBetaFeedback(packageName);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment.details;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.fragment.DetailsFragment;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.model.ExodusReport;
|
||||
import com.aurora.store.model.Report;
|
||||
import com.aurora.store.sheet.ExodusBottomSheet;
|
||||
import com.aurora.store.task.NetworkTask;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class ExodusPrivacy extends AbstractHelper {
|
||||
|
||||
public static final String EXODUS_PATH = "https://reports.exodus-privacy.eu.org/api/search/";
|
||||
|
||||
@BindView(R.id.exodus_card)
|
||||
RelativeLayout exodus_card;
|
||||
@BindView(R.id.moreButton)
|
||||
Button moreButton;
|
||||
|
||||
private Report report;
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
public ExodusPrivacy(DetailsFragment fragment, App app) {
|
||||
super(fragment, app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
ButterKnife.bind(this, view);
|
||||
get(EXODUS_PATH + app.getPackageName());
|
||||
}
|
||||
|
||||
private void get(String url) {
|
||||
disposable.add(Observable.fromCallable(() -> new NetworkTask(context)
|
||||
.get(url))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> {
|
||||
JSONObject jsonObject = new JSONObject(response);
|
||||
JSONObject exodusObject = jsonObject.getJSONObject(app.getPackageName());
|
||||
Gson gson = new Gson();
|
||||
ExodusReport exodusReport = gson.fromJson(exodusObject.toString(), ExodusReport.class);
|
||||
List<Report> reportList = exodusReport.getReports();
|
||||
Collections.sort(reportList, (Report1, Report2) ->
|
||||
Report2.getCreationDate().compareTo(Report1.getCreationDate()));
|
||||
report = reportList.get(0);
|
||||
drawExodus(report);
|
||||
}, throwable -> {
|
||||
Log.i("Error occurred at generating report");
|
||||
}));
|
||||
}
|
||||
|
||||
private void drawExodus(Report mReport) {
|
||||
if (context != null) {
|
||||
exodus_card.setVisibility(View.VISIBLE);
|
||||
if (mReport.getTrackers().size() > 0) {
|
||||
setText(view, R.id.exodus_description,
|
||||
new StringBuilder()
|
||||
.append(context.getString(R.string.exodus_hasTracker))
|
||||
.append(StringUtils.SPACE)
|
||||
.append(mReport.getTrackers().size()).toString());
|
||||
} else {
|
||||
setText(view, R.id.exodus_description, R.string.exodus_noTracker);
|
||||
}
|
||||
|
||||
if (mReport.getTrackers().isEmpty())
|
||||
moreButton.setVisibility(View.GONE);
|
||||
else
|
||||
moreButton.setOnClickListener(v -> showBottomDialog());
|
||||
}
|
||||
}
|
||||
|
||||
private void showBottomDialog() {
|
||||
ExodusBottomSheet bottomSheet = new ExodusBottomSheet(report);
|
||||
bottomSheet.show(fragment.getChildFragmentManager(), "EXODUS");
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.fragment.intro;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.activity.GoogleLoginActivity;
|
||||
import com.aurora.store.activity.IntroActivity;
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.NetworkUtil;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class LoginFragment extends IntroBaseFragment {
|
||||
|
||||
@BindView(R.id.btn_next)
|
||||
Button btnNext;
|
||||
@BindView(R.id.btn_anonymous)
|
||||
MaterialButton btnAnonymous;
|
||||
@BindView(R.id.progress_bar)
|
||||
ProgressBar progressBar;
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_intro_login, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_next)
|
||||
public void openLoginActivity() {
|
||||
context.startActivity(new Intent(context, GoogleLoginActivity.class));
|
||||
if (getActivity() instanceof IntroActivity)
|
||||
((IntroActivity) getActivity()).finish();
|
||||
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_anonymous)
|
||||
public void loginAnonymous() {
|
||||
if (!NetworkUtil.isConnected(context)) {
|
||||
Toast.makeText(context, getString(R.string.error_no_network), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
CompositeDisposable disposable = new CompositeDisposable();
|
||||
disposable.add(Observable.fromCallable(() -> PlayStoreApiAuthenticator
|
||||
.login(context))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnSubscribe(d -> {
|
||||
btnAnonymous.setText(getText(R.string.action_logging_in));
|
||||
btnAnonymous.setEnabled(false);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
})
|
||||
.subscribe(api -> {
|
||||
if (api != null) {
|
||||
Toast.makeText(context, getText(R.string.toast_login_success), Toast.LENGTH_SHORT).show();
|
||||
Intent intent = new Intent(context, AuroraActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation((IntroActivity) context);
|
||||
startActivity(intent, activityOptions.toBundle());
|
||||
((IntroActivity) getActivity()).finish();
|
||||
} else {
|
||||
Toast.makeText(context, getText(R.string.toast_login_failed), Toast.LENGTH_LONG).show();
|
||||
ContextUtil.runOnUiThread(this::resetAnonymousLogin);
|
||||
}
|
||||
}, err -> {
|
||||
Toast.makeText(context, getText(R.string.toast_login_failed), Toast.LENGTH_LONG).show();
|
||||
ContextUtil.runOnUiThread(this::resetAnonymousLogin);
|
||||
}));
|
||||
}
|
||||
|
||||
private void resetAnonymousLogin() {
|
||||
btnAnonymous.setEnabled(true);
|
||||
btnAnonymous.setText(getText(R.string.account_dummy));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInstaller;
|
||||
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.util.Log;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@@ -50,7 +50,8 @@ public class AppInstaller extends AppInstallerAbstract {
|
||||
public static AppInstaller getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
synchronized (AppInstaller.class) {
|
||||
if (instance == null) instance = new AppInstaller(context);
|
||||
if (instance == null)
|
||||
instance = new AppInstaller(context);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
|
||||
@@ -35,12 +35,15 @@ import androidx.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public abstract class AppInstallerAbstract {
|
||||
|
||||
private Context context;
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
private Handler handler = new Handler(Looper.getMainLooper());
|
||||
private InstallationStatusListener installationStatusListener;
|
||||
private InstallationStatusListener listener;
|
||||
|
||||
AppInstallerAbstract(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
@@ -54,26 +57,18 @@ public abstract class AppInstallerAbstract {
|
||||
};
|
||||
}
|
||||
|
||||
void addInstallationStatusListener(InstallationStatusListener installationStatusListener) {
|
||||
this.installationStatusListener = installationStatusListener;
|
||||
void addInstallationStatusListener(InstallationStatusListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
void dispatchSessionUpdate(int status, String packageName) {
|
||||
handler.post(() -> {
|
||||
if (installationStatusListener != null)
|
||||
installationStatusListener.onStatusChanged(status, packageName);
|
||||
if (listener != null)
|
||||
listener.onStatusChanged(status, packageName);
|
||||
});
|
||||
}
|
||||
|
||||
public BroadcastReceiver getBroadcastReceiver() {
|
||||
return broadcastReceiver;
|
||||
}
|
||||
|
||||
protected Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
protected abstract void installApkFiles(String packageName,List<File> apkFiles);
|
||||
protected abstract void installApkFiles(String packageName, List<File> apkFiles);
|
||||
|
||||
public interface InstallationStatusListener {
|
||||
void onStatusChanged(int status, @Nullable String packageName);
|
||||
|
||||
@@ -34,9 +34,9 @@ import com.aurora.services.IPrivilegedService;
|
||||
import com.aurora.store.BuildConfig;
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PackageUtil;
|
||||
import com.aurora.store.util.ContextUtil;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.PackageUtil;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -26,10 +26,10 @@ package com.aurora.store.installer;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInstaller;
|
||||
|
||||
import com.aurora.store.utility.ContextUtil;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.Root;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.ContextUtil;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.Root;
|
||||
import com.aurora.store.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
package com.aurora.store.installer;
|
||||
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.Root;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.Root;
|
||||
|
||||
public class AppUninstallerRooted {
|
||||
|
||||
|
||||
@@ -36,16 +36,18 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.aurora.store.AuroraApplication;
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.events.Event;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.notification.QuickNotification;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PathUtil;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.TextUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.ui.details.DetailsActivity;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.PathUtil;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
import com.aurora.store.util.TextUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -147,7 +149,7 @@ public class Installer implements AppInstallerAbstract.InstallationStatusListene
|
||||
displayName,
|
||||
statusMessage,
|
||||
getContentIntent(intentPackageName));
|
||||
sendLocalBroadcast(intentPackageName, 0);
|
||||
sendStatusBroadcast(intentPackageName, 0);
|
||||
checkAndProcessQueuedApps();
|
||||
break;
|
||||
case PackageInstaller.STATUS_SUCCESS:
|
||||
@@ -156,7 +158,7 @@ public class Installer implements AppInstallerAbstract.InstallationStatusListene
|
||||
displayName,
|
||||
statusMessage,
|
||||
getContentIntent(intentPackageName));
|
||||
sendLocalBroadcast(intentPackageName, 1);
|
||||
sendStatusBroadcast(intentPackageName, 1);
|
||||
if (app != null) {
|
||||
if (Util.shouldDeleteApk(context))
|
||||
clearInstallationFiles(app);
|
||||
@@ -200,24 +202,19 @@ public class Installer implements AppInstallerAbstract.InstallationStatusListene
|
||||
notificationManager.cancel(app.getPackageName().hashCode());
|
||||
}
|
||||
|
||||
private void sendLocalBroadcast(String packageName, int status) {
|
||||
Intent intent = new Intent("ACTION_INSTALL");
|
||||
intent.putExtra("PACKAGE_NAME", packageName);
|
||||
intent.putExtra("STATUS_CODE", status);
|
||||
context.sendBroadcast(intent);
|
||||
private void sendStatusBroadcast(String packageName, int status) {
|
||||
AuroraApplication.rxNotify(new Event(Event.SubType.INSTALLED, packageName, status));
|
||||
}
|
||||
|
||||
private PendingIntent getContentIntent(String packageName) {
|
||||
Intent intent = new Intent(context, DetailsActivity.class);
|
||||
intent.putExtra("INTENT_PACKAGE_NAME", packageName);
|
||||
intent.putExtra(Constants.INTENT_PACKAGE_NAME, packageName);
|
||||
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private AppInstallerAbstract getInstallationMethod(Context context) {
|
||||
String prefValue = PrefUtil.getString(context, Constants.PREFERENCE_INSTALLATION_METHOD);
|
||||
switch (prefValue) {
|
||||
case "0":
|
||||
return AppInstaller.getInstance(context);
|
||||
case "1":
|
||||
return AppInstallerRooted.getInstance(context);
|
||||
case "2":
|
||||
|
||||
@@ -13,8 +13,8 @@ import com.aurora.services.IPrivilegedCallback;
|
||||
import com.aurora.services.IPrivilegedService;
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
|
||||
public class Uninstaller {
|
||||
|
||||
@@ -51,12 +51,10 @@ public class Uninstaller {
|
||||
};
|
||||
try {
|
||||
if (!service.hasPrivilegedPermissions()) {
|
||||
Log.e("service.hasPrivilegedPermissions() is false");
|
||||
Log.d("service.hasPrivilegedPermissions() is false");
|
||||
return;
|
||||
}
|
||||
|
||||
service.deletePackage(app.getPackageName(), 1, callback);
|
||||
|
||||
} catch (RemoteException e) {
|
||||
Log.e("Connecting to privileged service failed");
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ package com.aurora.store.iterator;
|
||||
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.model.AppBuilder;
|
||||
import com.aurora.store.model.Filter;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.model.FilterModel;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.dragons.aurora.playstoreapiv2.AppListIterator;
|
||||
import com.dragons.aurora.playstoreapiv2.DocV2;
|
||||
|
||||
@@ -38,9 +38,9 @@ import java.util.Set;
|
||||
|
||||
public class CustomAppListIterator implements Iterator {
|
||||
|
||||
protected boolean filterEnabled = false;
|
||||
protected Filter filter = new Filter();
|
||||
protected AppListIterator iterator;
|
||||
private boolean filterEnabled = false;
|
||||
private FilterModel filterModel = new FilterModel();
|
||||
private AppListIterator iterator;
|
||||
private List<String> relatedTags = new ArrayList<>();
|
||||
|
||||
public CustomAppListIterator(AppListIterator iterator) {
|
||||
@@ -58,8 +58,8 @@ public class CustomAppListIterator implements Iterator {
|
||||
this.filterEnabled = filterEnabled;
|
||||
}
|
||||
|
||||
public void setFilter(Filter filter) {
|
||||
this.filter = filter;
|
||||
public void setFilterModel(FilterModel filterModel) {
|
||||
this.filterModel = filterModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,11 +87,11 @@ public class CustomAppListIterator implements Iterator {
|
||||
}
|
||||
|
||||
private boolean shouldSkip(App app) {
|
||||
return (!filter.isPaidApps() && !app.isFree())
|
||||
|| (!filter.isAppsWithAds() && app.containsAds())
|
||||
|| (!filter.isGsfDependentApps() && !app.getDependencies().isEmpty())
|
||||
|| (filter.getRating() > 0 && app.getRating().getAverage() < filter.getRating())
|
||||
|| (filter.getDownloads() > 0 && app.getInstalls() < filter.getDownloads());
|
||||
return (!filterModel.isPaidApps() && !app.isFree())
|
||||
|| (!filterModel.isAppsWithAds() && app.containsAds())
|
||||
|| (!filterModel.isGsfDependentApps() && !app.getDependencies().isEmpty())
|
||||
|| (filterModel.getRating() > 0 && app.getRating().getAverage() < filterModel.getRating())
|
||||
|| (filterModel.getDownloads() > 0 && app.getInstalls() < filterModel.getDownloads());
|
||||
}
|
||||
|
||||
private void addApp(List<App> apps, App app) {
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
package com.aurora.store.iterator;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.model.Review;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -33,15 +31,10 @@ import java.util.List;
|
||||
abstract public class ReviewIterator implements Iterator<List<Review>> {
|
||||
|
||||
protected String packageName;
|
||||
protected Context context;
|
||||
|
||||
protected int page = -1;
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setContext(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,13 @@
|
||||
|
||||
package com.aurora.store.iterator;
|
||||
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.AuroraApplication;
|
||||
import com.aurora.store.exception.InvalidApiException;
|
||||
import com.aurora.store.model.Review;
|
||||
import com.aurora.store.model.ReviewBuilder;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -39,6 +38,12 @@ public class ReviewRetrieverIterator extends ReviewIterator {
|
||||
static private final int PAGE_SIZE = 15;
|
||||
protected boolean hasNext = true;
|
||||
|
||||
private GooglePlayAPI.REVIEW_SORT reviewSort = GooglePlayAPI.REVIEW_SORT.HIGHRATING;
|
||||
|
||||
public void setReviewSort(GooglePlayAPI.REVIEW_SORT reviewSort) {
|
||||
this.reviewSort = reviewSort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return hasNext;
|
||||
@@ -49,7 +54,7 @@ public class ReviewRetrieverIterator extends ReviewIterator {
|
||||
page++;
|
||||
List<Review> list = new ArrayList<>();
|
||||
try {
|
||||
list.addAll(getReviews(packageName, PAGE_SIZE * page, PAGE_SIZE));
|
||||
list.addAll(getReviews(packageName, PAGE_SIZE * page, reviewSort));
|
||||
if (list.size() < PAGE_SIZE) {
|
||||
hasNext = false;
|
||||
}
|
||||
@@ -59,16 +64,16 @@ public class ReviewRetrieverIterator extends ReviewIterator {
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Review> getReviews(String packageId, int offset, int numberOfResults) throws Exception {
|
||||
private List<Review> getReviews(String packageId, int offset, GooglePlayAPI.REVIEW_SORT reviewSort) throws Exception {
|
||||
List<Review> reviews = new ArrayList<>();
|
||||
GooglePlayAPI api = PlayStoreApiAuthenticator.getInstance(context);
|
||||
GooglePlayAPI api = AuroraApplication.api;
|
||||
if (api == null)
|
||||
throw new InvalidApiException();
|
||||
for (com.dragons.aurora.playstoreapiv2.Review review : api.reviews(
|
||||
packageId,
|
||||
GooglePlayAPI.REVIEW_SORT.HELPFUL,
|
||||
reviewSort,
|
||||
offset,
|
||||
numberOfResults
|
||||
PAGE_SIZE
|
||||
).getGetResponse().getReviewList()) {
|
||||
reviews.add(ReviewBuilder.build(review));
|
||||
}
|
||||
|
||||
@@ -33,28 +33,31 @@ public class ReviewStorageIterator extends ReviewIterator {
|
||||
|
||||
static private final int PAGE_SIZE = 15;
|
||||
|
||||
private List<Review> list = new ArrayList<>();
|
||||
private List<Review> reviewList = new ArrayList<>();
|
||||
private ReviewRetrieverIterator iterator;
|
||||
|
||||
private ReviewRetrieverIterator getRetrievingIterator() {
|
||||
if (null == iterator) {
|
||||
iterator = new ReviewRetrieverIterator();
|
||||
iterator.setContext(context);
|
||||
iterator.setPackageName(packageName);
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
|
||||
public void setRetrievingIterator(ReviewRetrieverIterator iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return list.size() > (PAGE_SIZE * page) || getRetrievingIterator().hasNext();
|
||||
return reviewList.size() > (PAGE_SIZE * page) || getRetrievingIterator().hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Review> next() {
|
||||
page++;
|
||||
if (list.size() < (PAGE_SIZE * (page + 1)) && getRetrievingIterator().hasNext()) {
|
||||
list.addAll(getRetrievingIterator().next());
|
||||
if (reviewList.size() < (PAGE_SIZE * (page + 1)) && getRetrievingIterator().hasNext()) {
|
||||
reviewList.addAll(getRetrievingIterator().next());
|
||||
}
|
||||
return current();
|
||||
}
|
||||
@@ -71,6 +74,6 @@ public class ReviewStorageIterator extends ReviewIterator {
|
||||
private List<Review> current() {
|
||||
int from = PAGE_SIZE * page;
|
||||
int to = from + PAGE_SIZE;
|
||||
return (from < 0 || to > list.size()) ? new ArrayList<Review>() : list.subList(from, to);
|
||||
return (from < 0 || to > reviewList.size()) ? new ArrayList<Review>() : reviewList.subList(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Yalp Store
|
||||
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.manager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import com.aurora.store.utility.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class BitmapManager {
|
||||
|
||||
private File baseDir;
|
||||
|
||||
public BitmapManager(Context context) {
|
||||
baseDir = context.getCacheDir();
|
||||
}
|
||||
|
||||
static private void cacheBitmapOnDisk(Bitmap bitmap, File cached) {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(cached);
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static private Bitmap downloadBitmap(String url, boolean fullSize) {
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||
connection.connect();
|
||||
connection.setConnectTimeout(3000);
|
||||
InputStream input = connection.getInputStream();
|
||||
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
if (!fullSize) {
|
||||
options.inSampleSize = 4;
|
||||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
|
||||
return BitmapFactory.decodeStream(input, null, options);
|
||||
} catch (IOException e) {
|
||||
Log.e("Could not get icon from " + url + " " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public File downloadAndGetFile(String url) {
|
||||
File onDisk = getFile(url);
|
||||
Bitmap bitmap = downloadBitmap(url, true);
|
||||
if (null != bitmap) {
|
||||
cacheBitmapOnDisk(bitmap, onDisk);
|
||||
return onDisk;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private File getFile(String urlString) {
|
||||
return new File(baseDir, urlString.hashCode() + ".png");
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ package com.aurora.store.manager;
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -36,24 +36,22 @@ public class BlacklistManager {
|
||||
|
||||
public BlacklistManager(Context context) {
|
||||
this.context = context;
|
||||
blackList = PrefUtil.getListString(context, Constants.PREFERENCE_BLACKLIST_APPS_LIST);
|
||||
this.blackList = PrefUtil.getListString(context, Constants.PREFERENCE_BLACKLIST_APPS_LIST);
|
||||
}
|
||||
|
||||
public boolean add(String s) {
|
||||
public void add(String packageName) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
arrayList.add(s);
|
||||
boolean result = addAll(arrayList);
|
||||
arrayList.add(packageName);
|
||||
addAll(arrayList);
|
||||
save();
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean addAll(ArrayList<String> arrayList) {
|
||||
boolean result = blackList.addAll(arrayList);
|
||||
public void addAll(ArrayList<String> arrayList) {
|
||||
blackList.addAll(arrayList);
|
||||
Set<String> mAppSet = new HashSet<>(blackList);
|
||||
blackList.clear();
|
||||
blackList.addAll(mAppSet);
|
||||
save();
|
||||
return result;
|
||||
}
|
||||
|
||||
public ArrayList<String> get() {
|
||||
@@ -64,16 +62,19 @@ public class BlacklistManager {
|
||||
return blackList.contains(packageName);
|
||||
}
|
||||
|
||||
public boolean remove(String packageName) {
|
||||
boolean result = blackList.remove(packageName);
|
||||
public void remove(String packageName) {
|
||||
blackList.remove(packageName);
|
||||
save();
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean removeAll(ArrayList<String> packageList) {
|
||||
boolean result = blackList.removeAll(packageList);
|
||||
public void removeAll(ArrayList<String> packageList) {
|
||||
blackList.removeAll(packageList);
|
||||
save();
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
blackList = new ArrayList<>();
|
||||
save();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void save() {
|
||||
|
||||
@@ -27,26 +27,31 @@ import android.content.Context;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.SharedPreferencesTranslator;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.model.CategoryModel;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CategoryManager {
|
||||
|
||||
private static final String SUBCATEGORY_ID_GAMES = "GAME";
|
||||
private static final String SUBCATEGORY_ID_FAMILY = "FAMILY";
|
||||
|
||||
private Context context;
|
||||
private SharedPreferencesTranslator translator;
|
||||
private Gson gson;
|
||||
|
||||
public CategoryManager(Context context) {
|
||||
this.context = context;
|
||||
translator = new SharedPreferencesTranslator(Util.getPrefs(context));
|
||||
this.gson = new Gson();
|
||||
}
|
||||
|
||||
public static void clear(Context context) {
|
||||
PrefUtil.remove(context, Constants.CATEGORY_APPS);
|
||||
PrefUtil.remove(context, Constants.CATEGORY_GAME);
|
||||
PrefUtil.remove(context, Constants.CATEGORY_FAMILY);
|
||||
}
|
||||
|
||||
public String getCategoryName(String categoryId) {
|
||||
@@ -56,71 +61,31 @@ public class CategoryManager {
|
||||
if (categoryId.equals(Constants.TOP)) {
|
||||
return context.getString(R.string.title_all_apps);
|
||||
}
|
||||
return translator.getString(categoryId);
|
||||
}
|
||||
|
||||
public void save(String parent, Map<String, String> categories) {
|
||||
PrefUtil.putStringSet(context, parent, categories.keySet());
|
||||
for (String categoryId : categories.keySet()) {
|
||||
translator.putString(categoryId, categories.get(categoryId));
|
||||
}
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
public boolean fits(String appCategoryId, String chosenCategoryId) {
|
||||
return null == chosenCategoryId
|
||||
|| chosenCategoryId.equals(Constants.TOP)
|
||||
|| appCategoryId.equals(chosenCategoryId)
|
||||
|| PrefUtil.getStringSet(context, chosenCategoryId).contains(appCategoryId);
|
||||
|| appCategoryId.equals(chosenCategoryId);
|
||||
}
|
||||
|
||||
public boolean categoryListEmpty() {
|
||||
Set<String> topSet = PrefUtil.getStringSet(context, Constants.TOP);
|
||||
if (topSet.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
int size = topSet.size();
|
||||
String categoryId = topSet.toArray(new String[size])[size - 1];
|
||||
return translator.getString(categoryId).equals(categoryId);
|
||||
return PrefUtil.getString(context, Constants.CATEGORY_APPS).isEmpty();
|
||||
}
|
||||
|
||||
public Map<String, String> getAllCategories() {
|
||||
Map<String, String> categories = new TreeMap<>();
|
||||
Set<String> topSet = PrefUtil.getStringSet(context, Constants.TOP);
|
||||
for (String topCategoryId : topSet) {
|
||||
categories.put(topCategoryId, translator.getString(topCategoryId));
|
||||
}
|
||||
return categories;
|
||||
public List<CategoryModel> getCategories(String categoryId) {
|
||||
return getCategoryById(categoryId);
|
||||
}
|
||||
|
||||
public Map<String, String> getAllGames() {
|
||||
Map<String, String> games = new TreeMap<>();
|
||||
Set<String> topSet = PrefUtil.getStringSet(context, Constants.TOP);
|
||||
for (String topCategoryId : topSet) {
|
||||
Set<String> subSet = PrefUtil.getStringSet(context, topCategoryId);
|
||||
for (String subCategoryId : subSet) {
|
||||
if (subCategoryId.startsWith(SUBCATEGORY_ID_GAMES))
|
||||
games.put(subCategoryId, games.get(topCategoryId) + " - " + translator.getString(subCategoryId));
|
||||
}
|
||||
|
||||
}
|
||||
return games;
|
||||
}
|
||||
|
||||
public Map<String, String> getAllFamily() {
|
||||
Map<String, String> family = new TreeMap<>();
|
||||
Set<String> topSet = PrefUtil.getStringSet(context, Constants.TOP);
|
||||
for (String topCategoryId : topSet) {
|
||||
Set<String> subSet = PrefUtil.getStringSet(context, topCategoryId);
|
||||
for (String subCategoryId : subSet) {
|
||||
if (subCategoryId.startsWith(SUBCATEGORY_ID_FAMILY))
|
||||
family.put(subCategoryId, family.get(topCategoryId) + " - " + translator.getString(subCategoryId));
|
||||
}
|
||||
}
|
||||
return family;
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
Set<String> emptySet = new TreeSet<>();
|
||||
PrefUtil.putStringSet(context, Constants.TOP, emptySet);
|
||||
public List<CategoryModel> getCategoryById(String categoryId) {
|
||||
Type type = new TypeToken<List<CategoryModel>>() {
|
||||
}.getType();
|
||||
String jsonString = PrefUtil.getString(context, categoryId);
|
||||
List<CategoryModel> categoryList = gson.fromJson(jsonString, type);
|
||||
if (categoryList == null || categoryList.isEmpty())
|
||||
return new ArrayList<>();
|
||||
else
|
||||
return categoryList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ package com.aurora.store.manager;
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -32,7 +32,7 @@ import java.util.Set;
|
||||
public class FavouriteListManager {
|
||||
|
||||
private Context context;
|
||||
private ArrayList<String> favouriteList;
|
||||
private ArrayList<String> favouriteList = new ArrayList<>();
|
||||
|
||||
public FavouriteListManager(Context context) {
|
||||
this.context = context;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Yalp Store
|
||||
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.manager;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.model.FilterModel;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class FilterManager {
|
||||
|
||||
public static FilterModel getFilterPreferences(Context context) {
|
||||
Gson gson = new Gson();
|
||||
FilterModel filterModel = gson.fromJson(PrefUtil
|
||||
.getString(context, Constants.PREFERENCE_FILTER_APPS), FilterModel.class);
|
||||
if (filterModel == null) {
|
||||
FilterModel defaultModel = new FilterModel();
|
||||
PrefUtil.putString(context, Constants.PREFERENCE_FILTER_APPS, gson.toJson(defaultModel));
|
||||
return defaultModel;
|
||||
} else
|
||||
return filterModel;
|
||||
}
|
||||
|
||||
public static void saveFilterPreferences(Context context, FilterModel filterModel) {
|
||||
Gson gson = new Gson();
|
||||
String filterJSON = gson.toJson(filterModel);
|
||||
PrefUtil.putString(context, Constants.PREFERENCE_FILTER_APPS, filterJSON);
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.aurora.store.BuildConfig;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PathUtil;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.PathUtil;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
|
||||
@@ -25,7 +25,7 @@ package com.aurora.store.model;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.AggregateRating;
|
||||
import com.dragons.aurora.playstoreapiv2.AppDetails;
|
||||
import com.dragons.aurora.playstoreapiv2.Badge;
|
||||
|
||||
16
app/src/main/java/com/aurora/store/model/CategoryModel.java
Normal file
16
app/src/main/java/com/aurora/store/model/CategoryModel.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.aurora.store.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CategoryModel {
|
||||
String categoryId;
|
||||
String categoryTitle;
|
||||
String categoryImageUrl;
|
||||
|
||||
public CategoryModel(String categoryId, String categoryTitle, String categoryImageUrl) {
|
||||
this.categoryId = categoryId;
|
||||
this.categoryTitle = categoryTitle;
|
||||
this.categoryImageUrl = categoryImageUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.aurora.store.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ConnectionModel {
|
||||
private String typeName;
|
||||
private boolean isConnected;
|
||||
|
||||
public ConnectionModel(String typeName, boolean isConnected) {
|
||||
this.typeName = typeName;
|
||||
this.isConnected = isConnected;
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,13 @@ import com.aurora.store.Constants;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Filter {
|
||||
public class FilterModel {
|
||||
|
||||
private boolean systemApps;
|
||||
private boolean appsWithAds;
|
||||
private boolean paidApps;
|
||||
private boolean gsfDependentApps;
|
||||
private boolean systemApps = false;
|
||||
private boolean appsWithAds = true;
|
||||
private boolean paidApps = true;
|
||||
private boolean gsfDependentApps = true;
|
||||
private String category = Constants.TOP;
|
||||
private float rating;
|
||||
private int downloads;
|
||||
private float rating = 0.0f;
|
||||
private int downloads = 0;
|
||||
}
|
||||
@@ -26,8 +26,8 @@ package com.aurora.store.model;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.aurora.store.util.Accountant;
|
||||
import com.aurora.store.util.PrefUtil;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -20,16 +20,14 @@
|
||||
|
||||
package com.aurora.store.notification;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.utility.NotificationUtil;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.NotificationUtil;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
@@ -135,14 +133,6 @@ public class GeneralNotification extends NotificationBase {
|
||||
|
||||
public void show() {
|
||||
if (NotificationUtil.isNotificationEnabled(context)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
channel = new NotificationChannel(context.getPackageName(),
|
||||
context.getString(R.string.app_name),
|
||||
NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.setDescription("Aurora Store Notification Channel");
|
||||
manager.createNotificationChannel(channel);
|
||||
builder.setChannelId(channel.getId());
|
||||
}
|
||||
Glide.with(context.getApplicationContext())
|
||||
.asBitmap()
|
||||
.load(app.getIconInfo().getUrl())
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
package com.aurora.store.notification;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
@@ -28,14 +27,15 @@ import android.content.Intent;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.DetailsActivity;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.receiver.DownloadCancelReceiver;
|
||||
import com.aurora.store.receiver.DownloadPauseReceiver;
|
||||
import com.aurora.store.receiver.DownloadResumeReceiver;
|
||||
import com.aurora.store.receiver.InstallReceiver;
|
||||
import com.aurora.store.utility.NotificationUtil;
|
||||
import com.aurora.store.ui.details.DetailsActivity;
|
||||
import com.aurora.store.util.NotificationUtil;
|
||||
|
||||
public class NotificationBase {
|
||||
|
||||
@@ -44,7 +44,6 @@ public class NotificationBase {
|
||||
public static final String REQUEST_ID = "REQUEST_ID";
|
||||
|
||||
protected NotificationCompat.Builder builder;
|
||||
protected NotificationChannel channel;
|
||||
protected NotificationManager manager;
|
||||
|
||||
protected Context context;
|
||||
@@ -60,7 +59,7 @@ public class NotificationBase {
|
||||
}
|
||||
|
||||
protected NotificationCompat.Builder getBuilder() {
|
||||
return new NotificationCompat.Builder(context, app.getPackageName())
|
||||
return new NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_GENERAL)
|
||||
.setAutoCancel(true)
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
.setColorized(true)
|
||||
|
||||
@@ -20,24 +20,23 @@
|
||||
|
||||
package com.aurora.store.notification;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.utility.NotificationUtil;
|
||||
import com.aurora.store.util.NotificationUtil;
|
||||
|
||||
public class QuickNotification extends NotificationBase {
|
||||
|
||||
private static final int QUICK_NOTIFICATION_CHANNEL_ID = 69;
|
||||
|
||||
public QuickNotification(Context context) {
|
||||
private QuickNotification(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@@ -53,30 +52,19 @@ public class QuickNotification extends NotificationBase {
|
||||
public void show(String contentTitle, String contentText, PendingIntent contentIntent) {
|
||||
if (NotificationUtil.isNotificationEnabled(context)) {
|
||||
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
builder = new NotificationCompat.Builder(context, context.getPackageName())
|
||||
builder = new NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ALERT)
|
||||
.setAutoCancel(true)
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
.setColorized(true)
|
||||
.setColor(context.getResources().getColor(R.color.colorAccent))
|
||||
.setContentTitle(contentTitle)
|
||||
.setContentText(contentText)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||
.setSmallIcon(R.drawable.ic_notification);
|
||||
|
||||
if (contentIntent != null)
|
||||
builder.setContentIntent(contentIntent);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
channel = new NotificationChannel(
|
||||
context.getPackageName(),
|
||||
context.getString(R.string.app_name),
|
||||
NotificationManager.IMPORTANCE_LOW);
|
||||
channel.setDescription("Aurora Store Quick Notification Channel");
|
||||
manager.createNotificationChannel(channel);
|
||||
builder.setChannelId(channel.getId());
|
||||
}
|
||||
manager.notify(QUICK_NOTIFICATION_CHANNEL_ID, builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2019, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Yalp Store
|
||||
* Copyright (C) 2018 Sergey Yeriomin <yeriomin@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.provider;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.api.PlayStoreApiAuthenticator;
|
||||
import com.aurora.store.manager.BitmapManager;
|
||||
import com.aurora.store.utility.Accountant;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.PrefUtil;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayException;
|
||||
import com.dragons.aurora.playstoreapiv2.SearchSuggestEntry;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class AuroraSuggestionProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri) {
|
||||
return SearchManager.SUGGEST_MIME_TYPE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
|
||||
MatrixCursor cursor = new MatrixCursor(new String[]{
|
||||
BaseColumns._ID,
|
||||
SearchManager.SUGGEST_COLUMN_TEXT_1,
|
||||
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
||||
SearchManager.SUGGEST_COLUMN_ICON_1
|
||||
});
|
||||
try {
|
||||
fill(cursor, uri);
|
||||
} catch (Exception e) {
|
||||
Log.e(e.getMessage());
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
private void fill(MatrixCursor cursor, Uri uri) throws Exception {
|
||||
String query = uri.getLastPathSegment();
|
||||
if (TextUtils.isEmpty(query) || query.equals("search_suggest_query")) {
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
GooglePlayAPI api = PlayStoreApiAuthenticator.getInstance(getContext());
|
||||
for (SearchSuggestEntry entry : api.searchSuggest(query).getEntryList()) {
|
||||
cursor.addRow(constructRow(entry, i++));
|
||||
}
|
||||
}
|
||||
|
||||
private Object[] constructRow(SearchSuggestEntry entry, int id) {
|
||||
return entry.getType() == GooglePlayAPI.SEARCH_SUGGESTION_TYPE.APP.value ?
|
||||
constructAppRow(entry, id) : constructSuggestionRow(entry, id);
|
||||
}
|
||||
|
||||
private Object[] constructAppRow(SearchSuggestEntry entry, int id) {
|
||||
File file = new BitmapManager(getContext()).downloadAndGetFile(entry.getImageContainer().getImageUrl());
|
||||
return new Object[]{id, entry.getTitle(), entry.getPackageNameContainer().getPackageName(),
|
||||
null != file ? Uri.fromFile(file) : R.drawable.ic_placeholder};
|
||||
}
|
||||
|
||||
private Object[] constructSuggestionRow(SearchSuggestEntry entry, int id) {
|
||||
return new Object[]{id, entry.getSuggestedQuery(), entry.getSuggestedQuery(), R.drawable.ic_round_search};
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,6 @@ import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.aurora.store.utility.Log;
|
||||
|
||||
public class NativeGsfVersionProvider {
|
||||
|
||||
static private final String GOOGLE_SERVICES_PACKAGE_ID = "com.google.android.gms";
|
||||
|
||||
@@ -28,7 +28,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.util.Util;
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
||||
|
||||
@@ -8,14 +8,15 @@ import android.content.Intent;
|
||||
import com.aurora.store.AuroraApplication;
|
||||
import com.aurora.store.Constants;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.activity.AuroraActivity;
|
||||
import com.aurora.store.model.App;
|
||||
import com.aurora.store.notification.QuickNotification;
|
||||
import com.aurora.store.task.LiveUpdate;
|
||||
import com.aurora.store.task.ObservableDeliveryData;
|
||||
import com.aurora.store.task.UpdatableAppsTask;
|
||||
import com.aurora.store.utility.Log;
|
||||
import com.aurora.store.utility.Util;
|
||||
import com.aurora.store.ui.main.AuroraActivity;
|
||||
import com.aurora.store.util.Log;
|
||||
import com.aurora.store.util.Util;
|
||||
import com.dragons.aurora.playstoreapiv2.GooglePlayAPI;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -36,7 +37,7 @@ public class UpdatesReceiver extends BroadcastReceiver {
|
||||
this.context = context;
|
||||
Log.i("Update check Started");
|
||||
CompositeDisposable disposable = new CompositeDisposable();
|
||||
UpdatableAppsTask updatableAppTask = new UpdatableAppsTask(context);
|
||||
UpdatableAppsTask updatableAppTask = new UpdatableAppsTask(new GooglePlayAPI(), context);
|
||||
disposable.add(Observable.fromCallable(updatableAppTask::getUpdatableApps)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@@ -60,7 +61,7 @@ public class UpdatesReceiver extends BroadcastReceiver {
|
||||
|
||||
private void updateAllApps(List<App> updatableAppList) {
|
||||
AuroraApplication.setOngoingUpdateList(updatableAppList);
|
||||
AuroraApplication.setOnGoingUpdate(true);
|
||||
AuroraApplication.setBulkUpdateAlive(true);
|
||||
disposable.add(Observable.fromIterable(updatableAppList)
|
||||
.flatMap(app -> new ObservableDeliveryData(context).getDeliveryData(app))
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.aurora.store.section;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.aurora.store.GlideApp;
|
||||
import com.aurora.store.R;
|
||||
import com.aurora.store.model.App;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.github.luizgrp.sectionedrecyclerviewadapter.Section;
|
||||
import io.github.luizgrp.sectionedrecyclerviewadapter.SectionParameters;
|
||||
|
||||
public class BlackListedAppSection extends Section {
|
||||
|
||||
private Context context;
|
||||
private List<App> appList = new ArrayList<>();
|
||||
private List<String> blackList;
|
||||
private ClickListener clickListener;
|
||||
|
||||
public BlackListedAppSection(Context context, List<String> blackList, ClickListener clickListener) {
|
||||
super(SectionParameters.builder()
|
||||
.itemResourceId(R.layout.item_blacklist)
|
||||
.loadingResourceId(R.layout.item_loading)
|
||||
.emptyResourceId(R.layout.item_empty)
|
||||
.build());
|
||||
this.context = context;
|
||||
this.blackList = blackList;
|
||||
this.clickListener = clickListener;
|
||||
setState(State.LOADING);
|
||||
}
|
||||
|
||||
public void updateList(List<App> appList) {
|
||||
this.appList.clear();
|
||||
this.appList.addAll(appList);
|
||||
if (appList.isEmpty())
|
||||
setState(State.EMPTY);
|
||||
else
|
||||
setState(State.LOADED);
|
||||
}
|
||||
|
||||
public void remove(String packageName) {
|
||||
blackList.remove(packageName);
|
||||
}
|
||||
|
||||
public void add(String packageName) {
|
||||
blackList.add(packageName);
|
||||
}
|
||||
|
||||
public List<App> getList() {
|
||||
return appList;
|
||||
}
|
||||
|
||||
public List<String> getBlacklist() {
|
||||
return blackList;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentItemsTotal() {
|
||||
return appList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder getItemViewHolder(View view) {
|
||||
return new ContentHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder getEmptyViewHolder(View view) {
|
||||
return new EmptyHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder getLoadingViewHolder(View view) {
|
||||
return new LoadingHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
final ContentHolder contentHolder = (ContentHolder) holder;
|
||||
final App app = appList.get(position);
|
||||
|
||||
contentHolder.line1.setText(app.getDisplayName());
|
||||
contentHolder.line2.setText(app.getPackageName());
|
||||
contentHolder.checkBox.setChecked(blackList.contains(app.getPackageName()));
|
||||
|
||||
GlideApp
|
||||
.with(context)
|
||||
.load(app.getIconInfo().getUrl())
|
||||
.transforms(new CenterCrop(), new RoundedCorners(30))
|
||||
.into(contentHolder.img);
|
||||
|
||||
contentHolder.itemView.setOnClickListener(v -> {
|
||||
clickListener.onClick(position, app.getPackageName());
|
||||
});
|
||||
}
|
||||
|
||||
public interface ClickListener {
|
||||
void onClick(int position, String packageName);
|
||||
}
|
||||
|
||||
static class ContentHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.img)
|
||||
ImageView img;
|
||||
@BindView(R.id.line1)
|
||||
TextView line1;
|
||||
@BindView(R.id.line2)
|
||||
TextView line2;
|
||||
@BindView(R.id.check)
|
||||
MaterialCheckBox checkBox;
|
||||
|
||||
ContentHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
|
||||
static class EmptyHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.img)
|
||||
ImageView img;
|
||||
@BindView(R.id.line1)
|
||||
TextView line1;
|
||||
|
||||
EmptyHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
img.setImageDrawable(itemView.getResources().getDrawable(R.drawable.ic_menu_blacklist));
|
||||
line1.setText(itemView.getContext().getString(R.string.list_blacklist_none));
|
||||
}
|
||||
}
|
||||
|
||||
static class LoadingHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.progress_bar)
|
||||
ProgressBar progressBar;
|
||||
@BindView(R.id.line1)
|
||||
TextView line1;
|
||||
|
||||
LoadingHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user