/* * ____.____ __.____ ___ _____ * | | |/ _| | \ / _ \ ______ ______ * | | < | | / / /_\ \\____ \\____ \ * /\__| | | \| | / / | \ |_> > |_> > * \________|____|__ \______/ \____|__ / __/| __/ * \/ \/|__| |__| * * Copyright (c) 2014-2015 Paul "Marunjar" Pretsch * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * */ package org.voidsink.anewjkuapp.fragment; import android.accounts.Account; import android.content.ContentResolver; import android.content.Intent; import android.content.UriMatcher; import android.database.Cursor; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.format.DateUtils; import android.util.Log; import android.util.SparseIntArray; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import org.voidsink.anewjkuapp.R; import org.voidsink.anewjkuapp.analytics.Analytics; import org.voidsink.anewjkuapp.base.BaseContentObserver; import org.voidsink.anewjkuapp.base.BaseFragment; import org.voidsink.anewjkuapp.base.ContentObserverListener; import org.voidsink.anewjkuapp.calendar.CalendarContractWrapper; import org.voidsink.anewjkuapp.calendar.CalendarEventAdapter; import org.voidsink.anewjkuapp.calendar.CalendarListEvent; import org.voidsink.anewjkuapp.calendar.CalendarListItem; import org.voidsink.anewjkuapp.calendar.CalendarUtils; import org.voidsink.anewjkuapp.update.ImportCalendarTask; import org.voidsink.anewjkuapp.update.UpdateService; import org.voidsink.anewjkuapp.utils.AppUtils; import org.voidsink.anewjkuapp.utils.Consts; import org.voidsink.sectionedrecycleradapter.SectionedRecyclerViewAdapter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; public class CalendarFragment extends BaseFragment implements ContentObserverListener, LoaderManager.LoaderCallbacks<Cursor> { private static final String TAG = CalendarFragment.class.getSimpleName(); private long now = 0, then = 0; private CalendarEventAdapter mAdapter; private BaseContentObserver mDataObserver; private RecyclerView mRecyclerView; private Button mLoadMoreButton; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_calendar, container, false); mRecyclerView = (RecyclerView) view.findViewById(R.id.calendar_card_events); mLoadMoreButton = (Button) view.findViewById(R.id.calendar_card_load); mLoadMoreButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { loadMoreData(); } }); mLoadMoreButton.setClickable(true); setButtonLoadText(); return view; } private void setButtonLoadText() { mLoadMoreButton.setText(getContext().getString(R.string.listview_footer_button, SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM).format(then))); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (savedInstanceState != null) { now = savedInstanceState.getLong(Consts.ARG_CALENDAR_NOW, now); then = savedInstanceState.getLong(Consts.ARG_CALENDAR_THEN, then); setButtonLoadText(); } mAdapter = new CalendarEventAdapter(getContext()); // mListView.addFooterView(loadMore); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); mRecyclerView.setAdapter(new SectionedRecyclerViewAdapter(mRecyclerView, mAdapter)); mAdapter.setOnItemClickListener(new CalendarEventAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int viewType, int position) { if (position != RecyclerView.NO_POSITION) { CalendarListItem item = mAdapter.getItem(position); if (item != null) { ((CalendarListEvent) item).showOnMap(getContext()); } } } }); getLoaderManager().initLoader(0, null, this); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // init range now = System.currentTimeMillis(); then = now + 14 * DateUtils.DAY_IN_MILLIS; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putLong(Consts.ARG_CALENDAR_NOW, now); outState.putLong(Consts.ARG_CALENDAR_THEN, then); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.calendar, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_refresh_calendar: Intent mUpdateService = new Intent(getActivity(), UpdateService.class); mUpdateService.putExtra(Consts.ARG_UPDATE_CAL, true); getActivity().startService(mUpdateService); return true; case R.id.action_cal_goto_today: mRecyclerView.smoothScrollToPosition(0); return true; default: return super.onOptionsItemSelected(item); } } private void loadMoreData() { now = System.currentTimeMillis(); // if someone changed the time since last click // increase in month steps Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(then); then += cal.getActualMaximum(Calendar.DAY_OF_MONTH) * DateUtils.DAY_IN_MILLIS; // set button text setButtonLoadText(); Analytics.eventLoadMoreEvents(getContext(), then - now); loadData(); } private void loadData() { getLoaderManager().restartLoader(0, null, this); } @Override public void onStart() { super.onStart(); UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(CalendarContractWrapper.AUTHORITY(), CalendarContractWrapper.Events.CONTENT_URI().buildUpon().appendPath("#").build().toString(), 0); mDataObserver = new BaseContentObserver(uriMatcher, this); // listen to all changes getActivity().getContentResolver().registerContentObserver( CalendarContractWrapper.Events.CONTENT_URI().buildUpon() .appendPath("#").build(), false, mDataObserver); } @Override public void onStop() { super.onStop(); getActivity().getContentResolver().unregisterContentObserver( mDataObserver); mDataObserver = null; } @Override protected String getScreenName() { return Consts.SCREEN_CALENDAR; } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { showProgressIndeterminate(); Account mAccount = AppUtils.getAccount(getContext()); String calIDLva = CalendarUtils.getCalIDByName(getContext(), mAccount, CalendarUtils.ARG_CALENDAR_COURSE, true); String calIDExam = CalendarUtils.getCalIDByName(getContext(), mAccount, CalendarUtils.ARG_CALENDAR_EXAM, true); if (calIDLva == null || calIDExam == null) { Log.w(TAG, "no events loaded, calendars not found"); return null; } return new CursorLoader(getContext(), CalendarContractWrapper.Events.CONTENT_URI(), CalendarUtils.EVENT_PROJECTION, "(" + CalendarContractWrapper.Events .CALENDAR_ID() + " = ? or " + CalendarContractWrapper.Events .CALENDAR_ID() + " = ? ) and " + CalendarContractWrapper.Events.DTEND() + " >= ? and " + CalendarContractWrapper.Events.DTSTART() + " <= ? and " + CalendarContractWrapper.Events.DELETED() + " != 1", new String[]{calIDExam, calIDLva, Long.toString(now), Long.toString(then)}, CalendarContractWrapper.Events.DTSTART() + " ASC"); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mAdapter.clear(); Account mAccount = AppUtils.getAccount(getContext()); if (mAccount != null) { // fetch calendar colors final SparseIntArray mColors = new SparseIntArray(); ContentResolver cr = getContext().getContentResolver(); Cursor cursor = cr .query(CalendarContractWrapper.Calendars.CONTENT_URI(), new String[]{ CalendarContractWrapper.Calendars._ID(), CalendarContractWrapper.Calendars .CALENDAR_COLOR()}, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { mColors.put(cursor.getInt(0), cursor.getInt(1)); } cursor.close(); } List<CalendarListEvent> mEvents = new ArrayList<>(); if (data != null) { data.moveToFirst(); data.moveToPrevious(); while (data.moveToNext()) { mEvents.add(new CalendarListEvent( data.getLong(CalendarUtils.COLUMN_EVENT_ID), mColors.get(data .getInt(CalendarUtils.COLUMN_EVENT_CAL_ID)), data.getString(CalendarUtils.COLUMN_EVENT_TITLE), data.getString(CalendarUtils.COLUMN_EVENT_DESCRIPTION), data.getString(CalendarUtils.COLUMN_EVENT_LOCATION), data.getLong(CalendarUtils.COLUMN_EVENT_DTSTART), data.getLong(CalendarUtils.COLUMN_EVENT_DTEND))); } } mAdapter.addAll(mEvents); } mAdapter.notifyDataSetChanged(); finishProgress(); } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.clear(); mAdapter.notifyDataSetChanged(); finishProgress(); } @Override public void onContentChanged(boolean selfChange) { loadData(); } }