package pro.dbro.glance.activities;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.DialogFragment;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import java.util.List;
import pro.dbro.glance.adapters.AdapterUtils;
import pro.dbro.glance.GlanceApplication;
import pro.dbro.glance.GlancePrefsManager;
import pro.dbro.glance.R;
import pro.dbro.glance.SECRETS;
import pro.dbro.glance.billing.Catalog;
import pro.dbro.glance.billing.IabHelper;
import pro.dbro.glance.billing.IabResult;
import pro.dbro.glance.billing.Inventory;
import pro.dbro.glance.billing.Purchase;
import pro.dbro.glance.events.ChapterSelectRequested;
import pro.dbro.glance.events.ChapterSelectedEvent;
import pro.dbro.glance.events.WpmSelectedEvent;
import pro.dbro.glance.formats.HtmlPage;
import pro.dbro.glance.formats.SpritzerMedia;
import pro.dbro.glance.fragments.SpritzFragment;
import pro.dbro.glance.fragments.TocDialogFragment;
import pro.dbro.glance.fragments.WpmDialogFragment;
import pro.dbro.glance.lib.events.SpritzFinishedEvent;
public class MainActivity extends FragmentActivity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "MainActivity";
public static final boolean VERBOSE = false;
public static final String SPRITZ_FRAG_TAG = "spritzfrag";
private static final int THEME_LIGHT = 0;
private static final int THEME_DARK = 1;
private IabHelper mBillingHelper;
private boolean mIsPremium;
private Menu mMenu;
private boolean mFinishAfterSpritz = false;
// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
if (VERBOSE) Log.d(TAG, "Query inventory finished.");
// Have we been disposed of in the meantime? If so, quit.
if (mBillingHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
Log.i(TAG, "Failed to query inventory: " + result);
return;
}
if (VERBOSE) Log.d(TAG, "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
// Do we have the premium upgrade?
Purchase premiumPurchase = inventory.getPurchase(Catalog.SKU_PREMIUM);
boolean isPremiumUser = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
if (VERBOSE) Log.d(TAG, "User is " + (isPremiumUser ? "PREMIUM" : "NOT PREMIUM"));
if (VERBOSE) Log.d(TAG, "Initial inventory query finished; enabling main UI.");
mIsPremium = isPremiumUser;
invalidateOptionsMenu();
}
};
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
if (VERBOSE) Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
if (mBillingHelper == null) return;
if (result.isFailure()) {
Log.i(TAG, "Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayload(purchase)) {
Log.i(TAG, "Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(Catalog.SKU_PREMIUM)) {
// bought the premium upgrade!
if (VERBOSE) Log.d(TAG, "Purchase is premium upgrade. Congratulating user.");
showDonateCompleteDialog();
mIsPremium = true;
invalidateOptionsMenu();
}
}
};
private Bus mBus;
@Override
protected void onCreate(Bundle savedInstanceState) {
int theme = GlancePrefsManager.getTheme(this);
switch (theme) {
case THEME_LIGHT:
setTheme(R.style.Light);
break;
case THEME_DARK:
setTheme(R.style.Dark);
break;
}
super.onCreate(savedInstanceState);
setupActionBar();
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new SpritzFragment(), SPRITZ_FRAG_TAG)
.commit();
GlanceApplication app = (GlanceApplication) getApplication();
mBus = app.getBus();
mBus.register(this);
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
setupBillingConnection(SECRETS.getBillingPubKey());
}
@Override
public void onResume() {
super.onResume();
dimSystemUi(true);
boolean intentIncludesMediaUri = false;
String action = getIntent().getAction();
Uri intentUri = null;
if (!isIntentMarkedAsHandled(getIntent())) {
if (action.equals(Intent.ACTION_VIEW)) {
intentIncludesMediaUri = true;
intentUri = getIntent().getData();
} else if (action.equals(Intent.ACTION_SEND)) {
intentIncludesMediaUri = true;
intentUri = Uri.parse(getIntent().getStringExtra(Intent.EXTRA_TEXT));
}
if (intentIncludesMediaUri && intentUri != null) {
if (getIntent().hasExtra(AdapterUtils.FINISH_AFTER)) mFinishAfterSpritz = true;
SpritzFragment frag = getSpritzFragment();
frag.feedMediaUriToSpritzer(intentUri);
}
markIntentAsHandled(getIntent());
}
}
private void markIntentAsHandled(Intent intent) {
intent.putExtra("handled", true);
}
private boolean isIntentMarkedAsHandled(Intent intent) {
return intent.getBooleanExtra("handled", false);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mBus != null) {
mBus.unregister(this);
}
if (mBillingHelper != null) {
mBillingHelper.dispose();
mBillingHelper = null;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mMenu = menu;
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
// if (mIsPremium) {
// menu.removeItem(R.id.action_donate);
// }
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// if (mIsPremium) {
// menu.removeItem(R.id.action_donate);
// }
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_speed) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
DialogFragment newFragment = WpmDialogFragment.newInstance();
newFragment.show(ft, "dialog");
return true;
} else if (id == R.id.action_theme) {
int theme = GlancePrefsManager.getTheme(this);
if (theme == THEME_LIGHT) {
applyDarkTheme();
} else {
applyLightTheme();
}
}
/*
else if (id == R.id.action_open) {
getSpritzFragment().chooseMedia();
}
*/
// else if(id == R.id.action_donate) {
// showDonateDialog();
// }
return super.onOptionsItemSelected(item);
}
@Subscribe
public void onWpmSelected(WpmSelectedEvent event) {
if (getSpritzFragment() != null) {
getSpritzFragment().getSpritzer()
.setWpm(event.getWpm());
}
}
private void applyDarkTheme() {
GlancePrefsManager.setTheme(this, THEME_DARK);
recreate();
}
private void applyLightTheme() {
GlancePrefsManager.setTheme(this, THEME_LIGHT);
recreate();
}
@Subscribe
public void onSpritzFinished(SpritzFinishedEvent event) {
runOnUiThread(new Runnable() {
@Override
public void run() {
takeSharingActionifAppropriateAndFinish(getSpritzFragment().getSpritzer().getMedia());
}
});
}
@Subscribe
public void onChapterSelected(ChapterSelectedEvent event) {
SpritzFragment frag = getSpritzFragment();
if (frag != null && frag.getSpritzer() != null) {
frag.getSpritzer().printChapter(event.getChapter());
frag.updateMetaUi();
} else {
Log.e(TAG, "SpritzFragment not available to apply chapter selection");
}
}
@Subscribe
public void onChapterSelectRequested(ChapterSelectRequested ignored) {
SpritzFragment frag = getSpritzFragment();
if (frag != null && frag.isResumed() && frag.getSpritzer() != null) {
SpritzerMedia book = frag.getSpritzer().getMedia();
FragmentTransaction ft = getFragmentManager().beginTransaction();
DialogFragment newFragment = TocDialogFragment.newInstance(book);
newFragment.show(ft, "dialog");
} else {
Log.e(TAG, "SpritzFragment not available for chapter selection");
}
}
private SpritzFragment getSpritzFragment() {
return ((SpritzFragment) getSupportFragmentManager().findFragmentByTag(SPRITZ_FRAG_TAG));
}
private void setupActionBar() {
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
ActionBar actionBar = getActionBar();
actionBar.setTitle("");
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
}
private void dimSystemUi(boolean doDim) {
final boolean isIceCreamSandwich = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
if (isIceCreamSandwich) {
final View decorView = getWindow().getDecorView();
if (doDim) {
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(uiOptions);
} else {
decorView.setSystemUiVisibility(0);
decorView.setOnSystemUiVisibilityChangeListener(null);
}
}
}
@Override
public void onSystemUiVisibilityChange(int visibility) {
// Stay in low-profile mode
if ((visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) {
dimSystemUi(true);
}
}
private void setupBillingConnection(String base64EncodedPublicKey) {
// compute your public key and store it in base64EncodedPublicKey
mBillingHelper = new IabHelper(this, base64EncodedPublicKey);
mBillingHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
if (mBillingHelper == null) return;
// Query purchases
mBillingHelper.queryInventoryAsync(mGotInventoryListener);
}
});
}
/**
* Honor system payment validator.
*/
private boolean verifyDeveloperPayload(Purchase p) {
return true;
}
private void showDonateDialog() {
new AlertDialog.Builder(this)
.setTitle(getString(R.string.dialog_donate_title))
.setMessage(Html.fromHtml(getString(R.string.dialog_donate_msg)))
.setPositiveButton(getString(R.string.dialog_donate_positive_btn), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mBillingHelper.launchPurchaseFlow(MainActivity.this, Catalog.SKU_PREMIUM, Catalog.PREMIUM_REQUEST,
mPurchaseFinishedListener, "");
}
})
.setNeutralButton(getString(R.string.dialog_donate_neutral_btn), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://github.com/OnlyInAmerica/OpenSpritz-Android"));
startActivity(i);
}
})
.show();
}
private void showDonateCompleteDialog() {
new AlertDialog.Builder(this)
.setTitle(getString(R.string.dialog_donate_complete_title))
.setPositiveButton(getString(R.string.dialog_donate_complete_positive_btn), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
}
/**
* Take the appropriate sharing action based on the recorded Preference
*/
public void takeSharingActionifAppropriateAndFinish(SpritzerMedia media) {
if (!(media instanceof HtmlPage)) return;
boolean isInternalMedia = getIntent().getBooleanExtra(AdapterUtils.IS_INTERNAL_MEDIA, false);
if (isInternalMedia) {
recordHtmlPageRead((HtmlPage) media);
if (mFinishAfterSpritz) finish();
return;
}
GlancePrefsManager.SharePref sharePref = GlancePrefsManager.getShareMode(this);
switch (sharePref) {
case ALWAYS:
recordHtmlPageRead((HtmlPage) media);
case NEVER:
if (mFinishAfterSpritz) finish();
break;
case ASK:
showShareHtmlPageDialog((HtmlPage) media);
break;
}
}
private void showShareHtmlPageDialog(final HtmlPage page) {
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(getString(R.string.share_dialog_title))
.setMessage(getString(R.string.share_dialog_message))
.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
recordHtmlPageRead(page);
}
})
.setNegativeButton(getString(R.string.no), null);
AlertDialog dialog = builder.create();
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
if (mFinishAfterSpritz) MainActivity.this.finish();
}
});
dialog.show();
}
private void recordHtmlPageRead(final HtmlPage page) {
// Okay, so this is really shitty.
// I know.
// Here's the thing: I didn't know Parse can't do DISTINCT or GROUP BY.
// Now I do.
// Anyway, instead we're just incrementing a counter.
ParseQuery<ParseObject> query = ParseQuery.getQuery("Article");
query.whereEqualTo("url", page.getUrl());
query.whereEqualTo("title", page.getTitle());
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> scoreList, ParseException e) {
if (e == null) {
Log.d("score", "Retrieved " + scoreList.size() + " scores");
if (scoreList.isEmpty()) {
// Don't have the object, create it.
ParseObject article = new ParseObject("Article");
article.put("url", page.getUrl());
article.put("title", page.getTitle());
article.put("reads", 1);
article.saveInBackground();
return;
} else {
// Update object if we already have it.
ParseObject article = scoreList.get(0);
article.increment("reads");
article.saveInBackground();
}
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
}