package de.tum.in.tumcampusapp.activities; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.net.ConnectivityManager; import android.os.AsyncTask; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.view.ViewCompat; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.Menu; import android.view.MenuItem; import android.view.View; import de.tum.in.tumcampusapp.R; import de.tum.in.tumcampusapp.activities.generic.BaseActivity; import de.tum.in.tumcampusapp.adapters.CardsAdapter; import de.tum.in.tumcampusapp.auxiliary.NetUtils; import de.tum.in.tumcampusapp.cards.generic.Card; import de.tum.in.tumcampusapp.managers.CardManager; import de.tum.in.tumcampusapp.services.SilenceService; /** * Main activity displaying the cards and providing navigation with navigation drawer */ public class MainActivity extends BaseActivity implements SwipeRefreshLayout.OnRefreshListener { /** * Navigation Drawer */ private ActionBarDrawerToggle mDrawerToggle; private boolean registered; /** * Card list */ private RecyclerView mCardsView; private CardsAdapter mAdapter; private SwipeRefreshLayout mSwipeRefreshLayout; final BroadcastReceiver connectivityChangeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (NetUtils.isConnected(context)) { refreshCards(); runOnUiThread(new Runnable() { @Override public void run() { unregisterReceiver(connectivityChangeReceiver); registered = false; } }); } } }; public MainActivity() { super(R.layout.activity_main); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Setup pull to refresh mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.ptr_layout); mSwipeRefreshLayout.setOnRefreshListener(this); mSwipeRefreshLayout.setColorSchemeResources( R.color.color_primary, R.color.tum_A100, R.color.tum_A200); // Setup card RecyclerView mCardsView = (RecyclerView) findViewById(R.id.cards_view); registerForContextMenu(mCardsView); final LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); mCardsView.setLayoutManager(layoutManager); mCardsView.setHasFixedSize(true); //Swipe gestures new ItemTouchHelper(new MainActivityTouchHelperCallback()).attachToRecyclerView(mCardsView); // Start silence Service (if already started it will just invoke a check) Intent service = new Intent(this, SilenceService.class); this.startService(service); // Set the list's click listener mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) { /** * Called when a drawer has settled in a completely closed state. */ @Override public void onDrawerClosed(View view) { super.onDrawerClosed(view); MainActivity.this.invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() } /** * Called when a drawer has settled in a completely open state. */ @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); MainActivity.this.invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() } }; // Set the drawer toggle as the DrawerListener mDrawerLayout.addDrawerListener(mDrawerToggle); if (CardManager.getShouldRefresh() || CardManager.getCards() == null) { refreshCards(); } else { initAdapter(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. this.getMenuInflater().inflate(R.menu.menu_settings, menu); return true; } /** * Setup cards adapter */ private void initAdapter() { mAdapter = new CardsAdapter(); mCardsView.setAdapter(mAdapter); } @Override protected void onDestroy() { super.onDestroy(); if (registered) { unregisterReceiver(connectivityChangeReceiver); registered = false; } } /** * If drawer is expanded hide settings icon * * @param menu Menu instance * @return True if handled */ @Override public boolean onPrepareOptionsMenu(Menu menu) { // If the nav drawer is open, hide action items related to the content view boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList); menu.findItem(R.id.action_settings).setVisible(!drawerOpen); return super.onPrepareOptionsMenu(menu); } /** * Sync the toggle state after onRestoreInstanceState has occurred. * * @param savedInstanceState Saved instance state bundle */ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } /** * Let the drawer toggle handle configuration changes * * @param newConfig The new configuration */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } /** * Handle expansion of navigation drawer and settings menu item click * * @param item Clicked menu item * @return True if handled */ @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } // Opens the preferences screen if (item.getItemId() == R.id.action_settings) { startActivity(new Intent(this, UserPreferencesActivity.class)); } return super.onOptionsItemSelected(item); } /** * Show progress indicator and start updating cards in background */ public void refreshCards() { mSwipeRefreshLayout.setRefreshing(true); onRefresh(); } /** * Starts updating cards in background * Called when {@link SwipeRefreshLayout} gets triggered. */ @Override public void onRefresh() { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { CardManager.update(MainActivity.this); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); if (mAdapter == null) { initAdapter(); } else { mAdapter.notifyDataSetChanged(); } mSwipeRefreshLayout.setRefreshing(false); if (!registered && !NetUtils.isConnected(MainActivity.this)) { registerReceiver(connectivityChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); registered = true; } } }.execute(); } /** * Executed when the RestoreCard is pressed */ public void restoreCards(View view) { CardManager.restoreCards(this); refreshCards(); showToolbar(); } /** * Smoothly scrolls the RecyclerView to the top and dispatches nestedScrollingEvents to show * the Toolbar */ private void showToolbar() { mCardsView.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); mCardsView.dispatchNestedFling(0, Integer.MIN_VALUE, true); mCardsView.stopNestedScroll(); mCardsView.getLayoutManager().smoothScrollToPosition(mCardsView, null, 0); } /** * A touch helper class, Handles swipe to dismiss events */ private class MainActivityTouchHelperCallback extends ItemTouchHelper.SimpleCallback { public MainActivityTouchHelperCallback() { super(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT); } @Override public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { Card.CardViewHolder cardViewHolder = (Card.CardViewHolder) viewHolder; if (!cardViewHolder.getCurrentCard().isDismissible()) { return 0; } return super.getSwipeDirs(recyclerView, viewHolder); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { //Moving is not allowed as per flags return false; } @Override public boolean isLongPressDragEnabled() { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { Card.CardViewHolder cardViewHolder = (Card.CardViewHolder) viewHolder; final Card card = cardViewHolder.getCurrentCard(); final int lastPos = mAdapter.remove(card); final View coordinatorLayoutView = findViewById(R.id.coordinator); Snackbar.make(coordinatorLayoutView, R.string.card_dismissed, Snackbar.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Override public void onClick(View v) { mAdapter.insert(lastPos, card); mCardsView.getLayoutManager().smoothScrollToPosition(mCardsView, null, lastPos); } }).addCallback(new Snackbar.Callback() { @Override public void onDismissed(Snackbar snackbar, int event) { super.onDismissed(snackbar, event); if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) { //DISMISS_EVENT_ACTION means, the snackbar was dismissed via the undo button //and therefore, we didn't really dismiss the card card.discardCard(); } } }) .show(); } } }