/** * Copyright 2009 Joe LaPenna */ package com.joelapenna.foursquared; import com.joelapenna.foursquare.types.Group; import com.joelapenna.foursquare.types.Tip; import com.joelapenna.foursquare.types.Todo; import com.joelapenna.foursquare.types.Venue; import com.joelapenna.foursquared.app.LoadableListActivity; import com.joelapenna.foursquared.util.UserUtils; import com.joelapenna.foursquared.util.VenueUtils; import com.joelapenna.foursquared.widget.SeparatedListAdapter; import com.joelapenna.foursquared.widget.TipsListAdapter; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import java.util.List; /** * Shows tips left at a venue as a sectioned list adapter. Groups are split * into tips left by friends and tips left by everyone else. * * @author Joe LaPenna (joe@joelapenna.com) * @author Mark Wyszomierski (markww@gmail.com) * -modified to start TipActivity on tip click (2010-03-25) * -added photos for tips (2010-03-25) * -refactored for new VenueActivity design (2010-09-16) */ public class VenueTipsActivity extends LoadableListActivity { public static final String TAG = "VenueTipsActivity"; public static final boolean DEBUG = FoursquaredSettings.DEBUG; public static final String INTENT_EXTRA_VENUE = Foursquared.PACKAGE_NAME + ".VenueTipsActivity.INTENT_EXTRA_VENUE"; public static final String INTENT_EXTRA_RETURN_VENUE = Foursquared.PACKAGE_NAME + ".VenueTipsActivity.INTENT_EXTRA_RETURN_VENUE"; private static final int ACTIVITY_TIP = 500; private SeparatedListAdapter mListAdapter; private StateHolder mStateHolder; private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) Log.d(TAG, "onReceive: " + intent); finish(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); registerReceiver(mLoggedOutReceiver, new IntentFilter(Foursquared.INTENT_ACTION_LOGGED_OUT)); Object retained = getLastNonConfigurationInstance(); if (retained != null && retained instanceof StateHolder) { mStateHolder = (StateHolder) retained; setPreparedResultIntent(); } else { mStateHolder = new StateHolder(); if (getIntent().hasExtra(INTENT_EXTRA_VENUE)) { mStateHolder.setVenue((Venue)getIntent().getExtras().getParcelable(INTENT_EXTRA_VENUE)); } else { Log.e(TAG, "VenueTipsActivity requires a venue parcel its intent extras."); finish(); return; } } ensureUi(); } @Override public void onPause() { super.onPause(); if (isFinishing()) { mListAdapter.removeObserver(); } } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(mLoggedOutReceiver); } @Override public Object onRetainNonConfigurationInstance() { return mStateHolder; } private void ensureUi() { mListAdapter = new SeparatedListAdapter(this); if (mStateHolder.getTipsFriends().size() > 0) { TipsListAdapter adapter = new TipsListAdapter(this, ((Foursquared) getApplication()).getRemoteResourceManager(), R.layout.tip_list_item); adapter.setDisplayTipVenueTitles(false); adapter.setGroup(mStateHolder.getTipsFriends()); mListAdapter.addSection(getString(R.string.venue_tips_activity_section_friends, mStateHolder.getTipsFriends().size()), adapter); } TipsListAdapter adapter = new TipsListAdapter(this, ((Foursquared) getApplication()).getRemoteResourceManager(), R.layout.tip_list_item); adapter.setDisplayTipVenueTitles(false); adapter.setGroup(mStateHolder.getTipsAll()); mListAdapter.addSection(getString(R.string.venue_tips_activity_section_all, mStateHolder.getTipsAll().size()), adapter); ListView listView = getListView(); listView.setAdapter(mListAdapter); listView.setSmoothScrollbarEnabled(true); listView.setDividerHeight(0); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // The tip that was clicked won't have its venue member set, since we got // here by viewing the parent venue. In this case, we request that the tip // activity not let the user recursively start drilling down past here. // Create a dummy venue which has only the name and address filled in. Venue venue = new Venue(); venue.setName(mStateHolder.getVenue().getName()); venue.setAddress(mStateHolder.getVenue().getAddress()); venue.setCrossstreet(mStateHolder.getVenue().getCrossstreet()); Tip tip = (Tip)parent.getAdapter().getItem(position); tip.setVenue(venue); Intent intent = new Intent(VenueTipsActivity.this, TipActivity.class); intent.putExtra(TipActivity.EXTRA_TIP_PARCEL, tip); intent.putExtra(TipActivity.EXTRA_VENUE_CLICKABLE, false); startActivityForResult(intent, ACTIVITY_TIP); } }); setTitle(getString(R.string.venue_tips_activity_title, mStateHolder.getVenue().getName())); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == ACTIVITY_TIP && resultCode == Activity.RESULT_OK) { if (data.hasExtra(TipActivity.EXTRA_TIP_RETURNED)) { Tip tip = (Tip)data.getParcelableExtra(TipActivity.EXTRA_TIP_RETURNED); Todo todo = data.hasExtra(TipActivity.EXTRA_TODO_RETURNED) ? (Todo)data.getParcelableExtra(TipActivity.EXTRA_TODO_RETURNED) : null; updateTip(tip, todo); } } } private void updateTip(Tip tip, Todo todo) { mStateHolder.updateTip(tip, todo); mListAdapter.notifyDataSetInvalidated(); prepareResultIntent(); } private void prepareResultIntent() { Intent intent = new Intent(); intent.putExtra(INTENT_EXTRA_RETURN_VENUE, mStateHolder.getVenue()); mStateHolder.setPreparedResult(intent); setPreparedResultIntent(); } private void setPreparedResultIntent() { if (mStateHolder.getPreparedResult() != null) { setResult(Activity.RESULT_OK, mStateHolder.getPreparedResult()); } } private static class StateHolder { private Venue mVenue; private Group<Tip> mTipsFriends; private Group<Tip> mTipsAll; private Intent mPreparedResult; public StateHolder() { mPreparedResult = null; mTipsFriends = new Group<Tip>(); mTipsAll = new Group<Tip>(); } public Venue getVenue() { return mVenue; } public void setVenue(Venue venue) { mVenue = venue; mTipsFriends.clear(); mTipsAll.clear(); for (Tip tip : venue.getTips()) { if (UserUtils.isFriend(tip.getUser())) { mTipsFriends.add(tip); } else { mTipsAll.add(tip); } } } public Group<Tip> getTipsFriends() { return mTipsFriends; } public Group<Tip> getTipsAll() { return mTipsAll; } public Intent getPreparedResult() { return mPreparedResult; } public void setPreparedResult(Intent intent) { mPreparedResult = intent; } public void updateTip(Tip tip, Todo todo) { // Changes to a tip status can produce or remove a to-do for its // parent venue. VenueUtils.handleTipChange(mVenue, tip, todo); // Also update the tip from wherever it appears in the separated // list adapter sections. updateTip(tip, mTipsFriends); updateTip(tip, mTipsAll); } private void updateTip(Tip tip, List<Tip> target) { for (Tip it : target) { if (it.getId().equals(tip.getId())) { it.setStatus(tip.getStatus()); break; } } } } }