/* * Copyright 2012 The Stanford MobiSocial Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package mobisocial.musubi.ui.fragments; import java.util.Arrays; import java.util.Calendar; import mobisocial.metrics.MusubiMetrics; import mobisocial.musubi.App; import mobisocial.musubi.Helpers; import mobisocial.musubi.R; import mobisocial.musubi.model.MFeed; import mobisocial.musubi.model.MIdentity; import mobisocial.musubi.model.helpers.FeedManager; import mobisocial.musubi.model.helpers.IdentitiesManager; import mobisocial.musubi.model.helpers.MyAccountManager; import mobisocial.musubi.objects.IntroductionObj; import mobisocial.musubi.provider.MusubiContentProvider; import mobisocial.musubi.provider.MusubiContentProvider.Provided; import mobisocial.musubi.service.MusubiService; import mobisocial.musubi.ui.MusubiBaseActivity; import mobisocial.musubi.ui.fragments.FeedListFragment.FeedListAdapter; import mobisocial.musubi.ui.fragments.FeedListFragment.FeedSummaryLoader; import mobisocial.musubi.ui.util.UiUtil; import mobisocial.musubi.util.LessSpammyContentObserver; import mobisocial.socialkit.Obj; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.app.SupportActivity; import android.support.v4.content.Loader; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ListView; /** * Displays a list of all user-accessible threads (feeds). * */ public class ConversationsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> { private static final String TAG = "ConversationsFragment"; private static final boolean DBG = MusubiBaseActivity.DBG; private FeedListAdapter mFeeds; public static final String ARG_IDENTITY_ID = "identity_id"; private OnFeedSelectedListener mFeedSelectedListener; private SQLiteOpenHelper mDatabaseSource; private FeedManager mFeedManager; private long[] mFeedIds; private long mIdentityId; private Activity mActivity; private LessSpammyContentObserver mObserver; public ConversationsFragment() { if (DBG) Log.d(TAG, "Instantiating new ConversationsFragment"); } public interface OnFeedSelectedListener { public void onFeedSelected(int position, Uri feedUri); } @Override public void onAttach(SupportActivity activity) { super.onAttach(activity); mActivity = activity.asActivity(); if (DBG) Log.d(TAG, "Attaching FeedListFragment."); mFeedSelectedListener = (OnFeedSelectedListener) activity; mDatabaseSource = App.getDatabaseSource(mActivity); mFeedManager = new FeedManager(mDatabaseSource); mIdentityId = (getArguments() != null) ? getArguments().getLong(ARG_IDENTITY_ID) : 0; mFeedIds = mFeedManager.getFeedsForIdentityId(mIdentityId); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mObserver = new LessSpammyContentObserver(new Handler(mActivity.getMainLooper())) { @Override public void lessSpammyOnChange(boolean arg0) { if(mFeeds == null || !isAdded()) { return; } initLoaders(true); } }; } @Override public void onResume() { super.onResume(); mActivity.getContentResolver().registerContentObserver(MusubiService.PRIMARY_CONTENT_CHANGED, false, mObserver); mObserver.resetTimeout(); mObserver.dispatchChange(false); } @Override public void onPause() { super.onPause(); mActivity.getContentResolver().unregisterContentObserver(mObserver); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_feed_list, container, false); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (null != mActivity.findViewById(R.id.feed_view)) { getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); } Button startConversation = new Button(getActivity()); startConversation.setText("New conversation"); startConversation.setOnClickListener(mNewConversationListener); getListView().addHeaderView(startConversation); mFeeds = new FeedListAdapter(mActivity); mFeeds.setPinnedPartitionHeadersEnabled(false); for (int i = 0; i < FeedListFragment.DAYS_TO_SHOW+1; i++) { mFeeds.addPartition(false, true); } setListAdapter(mFeeds); /** Load the latest feeds in the background **/ initLoaders(false); mActivity.findViewById(R.id.start_something).setVisibility(View.GONE); } @Override public void onListItemClick(ListView l, View v, int position, long id) { getListView().setItemChecked(position, true); Long feedId = (Long)v.getTag(); Uri feedUri = MusubiContentProvider.uriForItem(Provided.FEEDS, feedId); int feedPosition = position - getListView().getHeaderViewsCount(); mFeedSelectedListener.onFeedSelected(feedPosition, feedUri); } void initLoaders(boolean restart) { LoaderManager lm = getLoaderManager(); Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); Bundle args = new Bundle(); args.putLong("start", cal.getTimeInMillis()); if (restart) { lm.restartLoader(0, args, this); } else { lm.initLoader(0, args, this); } cal.add(Calendar.DAY_OF_MONTH, -1); for (int i = 1; i < FeedListFragment.DAYS_TO_SHOW; i++) { long time = cal.getTimeInMillis(); args = new Bundle(); args.putLong("start", time); args.putLong("end", time + FeedListFragment.ONE_DAY); if (restart) { lm.restartLoader(i, args, this); } else { lm.initLoader(i, args, this); } cal.add(Calendar.DAY_OF_MONTH, -1); } args = new Bundle(); args.putLong("end", cal.getTimeInMillis() + FeedListFragment.ONE_DAY); if (restart) { lm.restartLoader(FeedListFragment.DAYS_TO_SHOW, args, this); } else { lm.initLoader(FeedListFragment.DAYS_TO_SHOW, args, this); } } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { StringBuilder selection = new StringBuilder(FeedManager.visibleFeedSelection(mFeedIds)); FeedSummaryLoader cl = new FeedSummaryLoader(getActivity(), selection.toString()); cl.setUpdateThrottle(500); return cl; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { mFeeds.changeCursor(loader.getId(), cursor); } @Override public void onLoaderReset(Loader<Cursor> arg0) { } View.OnClickListener mNewConversationListener = new View.OnClickListener() { @Override public void onClick(View v) { IdentitiesManager im = new IdentitiesManager(mDatabaseSource); MIdentity[] peeps = new MIdentity[2]; peeps[1] = im.getIdentityForId(mIdentityId); peeps[0] = im.getMyDefaultIdentity(peeps[1]); MFeed feed = mFeedManager.createExpandingFeed(im.getIdentityForId(mIdentityId)); UiUtil.addToWhitelistsIfNecessary(mFeedManager, new MyAccountManager(mDatabaseSource), mFeedManager.getFeedMembers(feed), true); Uri feedUri = MusubiContentProvider.uriForItem(Provided.FEEDS, feed.id_); Obj invitedObj = IntroductionObj.from(Arrays.asList(peeps), true); Helpers.sendToFeed(mActivity, invitedObj, feedUri); Intent view = new Intent(Intent.ACTION_VIEW); view.setDataAndType(feedUri, FeedManager.MIME_TYPE); view.setPackage(getActivity().getPackageName()); startActivity(view); App.getUsageMetrics(mActivity).report(MusubiMetrics.FEED_CREATED_FROM_PROFILE); } }; }