package cl.monsoon.s1next.view.activity;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.lang.ref.WeakReference;
import javax.inject.Inject;
import cl.monsoon.s1next.App;
import cl.monsoon.s1next.R;
import cl.monsoon.s1next.data.User;
import cl.monsoon.s1next.data.event.FontSizeChangeEvent;
import cl.monsoon.s1next.data.event.ThemeChangeEvent;
import cl.monsoon.s1next.data.pref.DownloadPreferencesManager;
import cl.monsoon.s1next.data.pref.ThemeManager;
import cl.monsoon.s1next.util.RxJavaUtil;
import cl.monsoon.s1next.view.dialog.ThreadGoDialogFragment;
import cl.monsoon.s1next.view.internal.CoordinatorLayoutAnchorDelegate;
import cl.monsoon.s1next.view.internal.CoordinatorLayoutAnchorDelegateImpl;
import cl.monsoon.s1next.view.internal.DrawerLayoutDelegate;
import cl.monsoon.s1next.view.internal.DrawerLayoutDelegateConcrete;
import cl.monsoon.s1next.view.internal.ToolbarDelegate;
import cl.monsoon.s1next.widget.EventBus;
import rx.Subscription;
/**
* A base Activity which includes the Toolbar
* and navigation drawer amongst others.
* Also changes theme depends on settings.
*/
public abstract class BaseActivity extends AppCompatActivity
implements CoordinatorLayoutAnchorDelegate {
private static final int REQUEST_CODE_MESSAGE_IF_SUCCESS = 0;
private static final String EXTRA_MESSAGE = "message";
@Inject
EventBus mEventBus;
@Inject
User mUser;
@Inject
DownloadPreferencesManager mDownloadPreferencesManager;
@Inject
ThemeManager mThemeManager;
private ToolbarDelegate mToolbarDelegate;
private DrawerLayoutDelegate mDrawerLayoutDelegate;
private boolean mDrawerIndicatorEnabled = true;
private CoordinatorLayoutAnchorDelegate mCoordinatorLayoutAnchorDelegate;
@Nullable
private WeakReference<Snackbar> mSnackbar;
private Subscription mSubscription;
/**
* @see #setResultMessage(Activity, CharSequence)
* @see #onActivityResult(int, int, Intent)
*/
static void startActivityForResultMessage(Activity activity, Intent intent) {
activity.startActivityForResult(intent, REQUEST_CODE_MESSAGE_IF_SUCCESS);
}
/**
* Sets result message to {@link Activity} in order to show a short {@link Snackbar}
* for this message during {@link #onActivityResult(int, int, Intent)}.
*
* @param message The message to show.
* @see #startActivityForResultMessage(Activity, Intent)
* @see #onActivityResult(int, int, Intent)
*/
public static void setResultMessage(Activity activity, CharSequence message) {
Intent intent = new Intent();
intent.putExtra(EXTRA_MESSAGE, message);
activity.setResult(Activity.RESULT_OK, intent);
}
@Override
@CallSuper
protected void onCreate(Bundle savedInstanceState) {
App.getAppComponent(this).inject(this);
// change the theme depends on preference
if (!mThemeManager.isDefaultTheme()) {
setTheme(mThemeManager.getThemeStyle());
}
super.onCreate(savedInstanceState);
mSubscription = mEventBus.get().subscribe(o -> {
// recreate this Activity when theme or font size changes
if (o instanceof ThemeChangeEvent || o instanceof FontSizeChangeEvent) {
getWindow().setWindowAnimations(R.style.Animation_Recreate);
recreate();
}
});
}
@Override
@CallSuper
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
setupToolbar();
setupCoordinatorLayoutAnchorDelegate();
}
@Override
@CallSuper
public void setContentView(View view, ViewGroup.LayoutParams params) {
super.setContentView(view, params);
setupToolbar();
setupCoordinatorLayoutAnchorDelegate();
}
@Override
@CallSuper
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setupDrawer();
}
@Override
protected void onDestroy() {
super.onDestroy();
RxJavaUtil.unsubscribeIfNotNull(mSubscription);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// we show thread go menu only if this Activity has drawer
if (mDrawerLayoutDelegate != null) {
getMenuInflater().inflate(R.menu.thread_go, menu);
}
return super.onCreateOptionsMenu(menu);
}
@Override
@CallSuper
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app drawer touch event.
if (mDrawerLayoutDelegate != null && mDrawerLayoutDelegate.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case android.R.id.home:
// According to https://developer.android.com/design/patterns/navigation.html
// we should navigate to its hierarchical parent of the current screen.
// But the hierarchical logical is too complex in our app (sub forum, link redirection),
// so we use finish() to close the current Activity.
// looks the newest Google Play does the same way
finish();
return true;
case R.id.menu_thread_go:
new ThreadGoDialogFragment().show(getSupportFragmentManager(),
ThreadGoDialogFragment.TAG);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
@CallSuper
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mDrawerLayoutDelegate != null) {
mDrawerLayoutDelegate.onConfigurationChanged(newConfig);
}
}
/**
* @see #startActivityForResultMessage(Activity, Intent)
* @see #setResultMessage(Activity, CharSequence)
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_MESSAGE_IF_SUCCESS) {
if (resultCode == Activity.RESULT_OK) {
// We can't use #showShortText(String) because #onActivityResult(int, int, Intent)
// is always invoked when current app is running in the foreground (so we are
// unable to show a Toast if our app is running in the background).
showShortSnackbar(data.getStringExtra(EXTRA_MESSAGE));
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void setupToolbar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
mToolbarDelegate = new ToolbarDelegate(this, toolbar);
}
}
/**
* Sets Toolbar's navigation icon to cross.
*/
final void setupNavCrossIcon() {
mToolbarDelegate.setupNavCrossIcon();
}
final Optional<Toolbar> getToolbar() {
if (mToolbarDelegate == null) {
return Optional.absent();
} else {
return Optional.of(mToolbarDelegate.getToolbar());
}
}
private void setupDrawer() {
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawerLayout != null) {
mDrawerLayoutDelegate = new DrawerLayoutDelegateConcrete(this, drawerLayout,
(NavigationView) findViewById(R.id.navigation_view));
mDrawerLayoutDelegate.setDrawerIndicatorEnabled(mDrawerIndicatorEnabled);
mDrawerLayoutDelegate.onPostCreate();
}
}
/**
* Calls this method before {@link #onPostCreate(Bundle)}
* otherwise it doesn't works.
*/
final void disableDrawerIndicator() {
mDrawerIndicatorEnabled = false;
}
private void setupCoordinatorLayoutAnchorDelegate() {
mCoordinatorLayoutAnchorDelegate = new CoordinatorLayoutAnchorDelegateImpl(
(CoordinatorLayout) Preconditions.checkNotNull(findViewById(R.id.coordinator_layout)));
}
@Override
public final void setupFloatingActionButton(@DrawableRes int resId, View.OnClickListener onClickListener) {
mCoordinatorLayoutAnchorDelegate.setupFloatingActionButton(resId, onClickListener);
}
@Override
public final Optional<Snackbar> showShortText(CharSequence text) {
return saveSnackbarWeakReference(mCoordinatorLayoutAnchorDelegate.showShortText(text));
}
@Override
public final Optional<Snackbar> showShortSnackbar(@StringRes int resId) {
return saveSnackbarWeakReference(mCoordinatorLayoutAnchorDelegate.showShortSnackbar(resId));
}
@Override
public Optional<Snackbar> showShortSnackbar(CharSequence text) {
return saveSnackbarWeakReference(mCoordinatorLayoutAnchorDelegate.showShortSnackbar(text));
}
@Override
public final Optional<Snackbar> showLongSnackbarIfVisible(CharSequence text, @StringRes int actionResId, View.OnClickListener onClickListener) {
return saveSnackbarWeakReference(mCoordinatorLayoutAnchorDelegate.showShortSnackbar(text));
}
@Override
public final void dismissSnackbarIfExist() {
if (mSnackbar != null) {
Snackbar snackbar = mSnackbar.get();
if (snackbar != null && snackbar.isShownOrQueued()) {
snackbar.dismiss();
}
mSnackbar = null;
}
}
private Optional<Snackbar> saveSnackbarWeakReference(Optional<Snackbar> snackbar) {
if (snackbar.isPresent()) {
mSnackbar = new WeakReference<>(snackbar.get());
}
return snackbar;
}
}