package co.smartreceipts.android.rating;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import co.smartreceipts.android.di.scopes.ApplicationScope;
import co.smartreceipts.android.rating.data.AppRatingStorage;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
@ApplicationScope
public class AppRatingManager {
// AppRating (Use a combination of launches and a timer for the app rating
// to ensure that we aren't prompting new users too soon
private static final int LAUNCHES_UNTIL_PROMPT = 15;
private static final int DAYS_UNTIL_PROMPT = 7;
private AppRatingStorage appRatingStorage;
@Inject
AppRatingManager(AppRatingStorage appRatingStorage) {
this.appRatingStorage = appRatingStorage;
setCustomUncaughtExceptionHandler();
}
public Single<Boolean> checkIfNeedToAskRating() {
return appRatingStorage.readAppRatingData()
.map(appRatingModel -> {
if (appRatingModel.canShow() && !appRatingModel.isCrashOccurred()) {
// Check if we've reached a rating event
final long daysToMillis = TimeUnit.DAYS.toMillis(1);
if (appRatingModel.getLaunchCount() >= LAUNCHES_UNTIL_PROMPT + appRatingModel.getAdditionalLaunchThreshold() &&
(System.currentTimeMillis() - appRatingModel.getInstallTime()) / daysToMillis >= DAYS_UNTIL_PROMPT) {
return true;
}
}
return false;
})
.subscribeOn(Schedulers.io());
}
public void dontShowRatingPromptAgain() {
appRatingStorage.setDontShowRatingPromptMore();
}
public void prorogueRatingPrompt() {
appRatingStorage.prorogueRatingPrompt(LAUNCHES_UNTIL_PROMPT);
}
private void setCustomUncaughtExceptionHandler() {
Thread.UncaughtExceptionHandler exceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
if (!(exceptionHandler instanceof RatingUncaughtExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new RatingUncaughtExceptionHandler(appRatingStorage, exceptionHandler));
}
}
private static final class RatingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final AppRatingStorage sAppRatingStorage;
private final Thread.UncaughtExceptionHandler sUncaughtExceptionHandler;
public RatingUncaughtExceptionHandler(AppRatingStorage appRatingStorage, Thread.UncaughtExceptionHandler exceptionHandler) {
sAppRatingStorage = appRatingStorage;
sUncaughtExceptionHandler = exceptionHandler;
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
sAppRatingStorage.crashOccurred();
sUncaughtExceptionHandler.uncaughtException(thread, throwable);
}
}
}