package be.digitalia.fosdem.fragments;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.support.v4.content.SharedPreferencesCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import be.digitalia.fosdem.R;
import be.digitalia.fosdem.adapters.BookmarksAdapter;
import be.digitalia.fosdem.db.DatabaseManager;
import be.digitalia.fosdem.loaders.SimpleCursorLoader;
import be.digitalia.fosdem.providers.BookmarksExportProvider;
/**
* Bookmarks list, optionally filterable.
*
* @author Christophe Beyls
*/
public class BookmarksListFragment extends RecyclerViewFragment implements LoaderCallbacks<Cursor> {
private static final int BOOKMARKS_LOADER_ID = 1;
private static final String PREF_UPCOMING_ONLY = "bookmarks_upcoming_only";
private static final String STATE_ADAPTER = "adapter";
private BookmarksAdapter adapter;
private boolean upcomingOnly;
private MenuItem filterMenuItem;
private MenuItem upcomingOnlyMenuItem;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
adapter = new BookmarksAdapter((AppCompatActivity) getActivity());
if (savedInstanceState != null) {
adapter.onRestoreInstanceState(savedInstanceState.getParcelable(STATE_ADAPTER));
}
upcomingOnly = getActivity().getPreferences(Context.MODE_PRIVATE).getBoolean(PREF_UPCOMING_ONLY, false);
setHasOptionsMenu(true);
}
@Override
protected void onRecyclerViewCreated(RecyclerView recyclerView, Bundle savedInstanceState) {
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(adapter);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setEmptyText(getString(R.string.no_bookmark));
setProgressBarVisible(true);
getLoaderManager().initLoader(BOOKMARKS_LOADER_ID, null, this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(STATE_ADAPTER, adapter.onSaveInstanceState());
}
@Override
public void onDestroyView() {
adapter.onDestroyView();
super.onDestroyView();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.bookmarks, menu);
filterMenuItem = menu.findItem(R.id.filter);
upcomingOnlyMenuItem = menu.findItem(R.id.upcoming_only);
updateFilterMenuItem();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
menu.findItem(R.id.export_bookmarks).setEnabled(false).setVisible(false);
}
}
private void updateFilterMenuItem() {
if (filterMenuItem != null) {
filterMenuItem.setIcon(upcomingOnly ?
R.drawable.ic_filter_list_selected_white_24dp
: R.drawable.ic_filter_list_white_24dp);
upcomingOnlyMenuItem.setChecked(upcomingOnly);
}
}
@Override
public void onDestroyOptionsMenu() {
super.onDestroyOptionsMenu();
filterMenuItem = null;
upcomingOnlyMenuItem = null;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.upcoming_only:
upcomingOnly = !upcomingOnly;
updateFilterMenuItem();
SharedPreferencesCompat.EditorCompat.getInstance().apply(
getActivity().getPreferences(Context.MODE_PRIVATE).edit().putBoolean(PREF_UPCOMING_ONLY, upcomingOnly)
);
getLoaderManager().restartLoader(BOOKMARKS_LOADER_ID, null, this);
return true;
case R.id.export_bookmarks:
Intent exportIntent = BookmarksExportProvider.getIntent(getActivity());
startActivity(Intent.createChooser(exportIntent, getString(R.string.export_bookmarks)));
return true;
}
return false;
}
private static class BookmarksLoader extends SimpleCursorLoader {
// Events that just started are still shown for 5 minutes
private static final long TIME_OFFSET = 5L * DateUtils.MINUTE_IN_MILLIS;
private final boolean upcomingOnly;
private final Handler handler;
private final Runnable timeoutRunnable = new Runnable() {
@Override
public void run() {
onContentChanged();
}
};
public BookmarksLoader(Context context, boolean upcomingOnly) {
super(context);
this.upcomingOnly = upcomingOnly;
this.handler = new Handler();
}
@Override
public void deliverResult(Cursor cursor) {
if (upcomingOnly && !isReset()) {
handler.removeCallbacks(timeoutRunnable);
// The loader will be refreshed when the start time of the first bookmark in the list is reached
if ((cursor != null) && cursor.moveToFirst()) {
long startTime = DatabaseManager.toEventStartTimeMillis(cursor);
if (startTime != -1L) {
long delay = startTime - (System.currentTimeMillis() - TIME_OFFSET);
if (delay > 0L) {
handler.postDelayed(timeoutRunnable, delay);
} else {
onContentChanged();
}
}
}
}
super.deliverResult(cursor);
}
@Override
protected void onReset() {
super.onReset();
if (upcomingOnly) {
handler.removeCallbacks(timeoutRunnable);
}
}
@Override
protected Cursor getCursor() {
return DatabaseManager.getInstance().getBookmarks(upcomingOnly ? System.currentTimeMillis() - TIME_OFFSET : 0L);
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new BookmarksLoader(getActivity(), upcomingOnly);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data != null) {
adapter.swapCursor(data);
}
setProgressBarVisible(false);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
}