package com.gettingmobile.goodnews.home; import android.app.Application; import android.database.sqlite.SQLiteDatabase; import android.view.ContextMenu; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import com.gettingmobile.android.app.DialogFactory; import com.gettingmobile.android.app.actions.AbstractAction; import com.gettingmobile.android.app.actions.ActionContext; import com.gettingmobile.android.widget.ListItem; import com.gettingmobile.goodnews.ElementListActivity; import com.gettingmobile.goodnews.R; import com.gettingmobile.goodnews.account.AccountHandler; import com.gettingmobile.goodnews.account.LoginCallback; import com.gettingmobile.goodnews.changelog.ChangelogController; import com.gettingmobile.goodnews.download.ContentDownloadAction; import com.gettingmobile.goodnews.feedlist.FeedListActivity; import com.gettingmobile.goodnews.itemlist.ItemListActivity; import com.gettingmobile.goodnews.settings.SettingsHandler; import com.gettingmobile.goodnews.settings.TagListSettingsHandler; import com.gettingmobile.goodnews.sync.FullSyncAction; import com.gettingmobile.goodnews.sync.PushSyncAction; import com.gettingmobile.goodnews.sync.SyncListener; import com.gettingmobile.goodnews.sync.SyncService; import com.gettingmobile.goodnews.tip.RatingRequestDialog; import com.gettingmobile.goodnews.tip.TipDialogHandler; import com.gettingmobile.goodnews.util.TagFilter; import com.gettingmobile.google.reader.Feed; import com.gettingmobile.google.reader.ItemState; import com.gettingmobile.google.reader.SortedElement; import com.gettingmobile.google.reader.Tag; import com.gettingmobile.google.reader.db.FeedDatabaseAdapter; import com.gettingmobile.google.reader.db.ItemDatabaseAdapter; import com.gettingmobile.google.reader.db.TagDatabaseAdapter; import java.util.*; public final class HomeActivity extends ElementListActivity implements AdapterView.OnItemClickListener, OnFolderEdgeButtonClickListener, SyncListener { private final TagDatabaseAdapter labelAdapter = new TagDatabaseAdapter(); private final FeedDatabaseAdapter feedAdapter = new FeedDatabaseAdapter(); private final ItemDatabaseAdapter itemAdapter = new ItemDatabaseAdapter(); private final HomeListAdapter listAdapter = new HomeListAdapter(this); private FullSyncAction fullSyncAction = null; private PushSyncAction pushSyncAction = null; public HomeActivity() { super(R.integer.tip_group_tag_list); final TagListInflator tagListInflator = new TagListInflator(); setViewLoader(tagListInflator); setViewUpdater(tagListInflator); } @Override protected ListView getListView() { return (ListView) findViewById(R.id.tags); } @Override protected boolean showActionBarIconAsUp() { return false; } /* * life cycle management */ @Override public void onCreate() { setContentView(R.layout.tag_list); super.onCreate(); /* * handle click events */ final ListView listView = getListView(); listView.setOnItemClickListener(this); registerForContextMenu(listView); listAdapter.init(this); listView.setAdapter(listAdapter); } @Override protected void onRestart() { super.onRestart(); promptForAccount(); } @Override protected void onStart() { super.onStart(); getApp().getSyncService().addListener(this); } @Override protected void onResume() { if (!showWelcomeTips()) { if (!promptForAccount()) { if (!ChangelogController.automaticallyShowChangelogIfApplicable(getApp(), this)) { RatingRequestDialog.showIfApplicable(this); } } } super.onResume(); } @Override protected void onStop() { getApp().getSyncService().removeListener(this); super.onStop(); } @Override protected void onDestroy() { fullSyncAction.onDestroy(); pushSyncAction.onDestroy(); super.onDestroy(); } @Override protected void closeCursor() { listAdapter.close(); } /* * helpers */ private boolean showWelcomeTips() { return TipDialogHandler.start(getApp(), this, getApp().getTipManager(), R.integer.tip_group_welcome, true); } private boolean promptForAccount() { final AccountHandler accountHandler = getApp().getAccountHandler(); if (!accountHandler.hasAccount() && !accountHandler.isPromptShowing()) { accountHandler.promptAccount(this, new LoginCallback() { @Override public void onLoginStarted() { showWaitDialog(); } @Override public void onLoginFinished(Throwable error) { dismissWaitDialog(); if (error != null) { DialogFactory.showErrorDialog(HomeActivity.this, R.string.login_title, getString(R.string.login_failed)); } } }); return true; } else { return false; } } protected void openItemList(Tag tag) { startActivity(ItemListActivity.class, tag); } protected void openFeedList(Tag tag) { startActivity(FeedListActivity.class, tag); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final int viewId = parent.getId(); if (viewId == R.id.tags) { final SortedElement element = getItem(position); if (element != null && element instanceof Tag) { onTagClick((Tag) element); } else if (element != null && element instanceof Feed) { onFeedClick((Feed) element); } } } public void onTagClick(Tag tag) { if (tag.isFeedFolder() && !getApp().getSettings().folderClickOpensItemList()) { openFeedList(tag); } else { openItemList(tag); } } @Override public void onFolderEdgeButtonClick(Tag tag) { if (getApp().getSettings().folderClickOpensItemList()) { openFeedList(tag); } else { openItemList(tag); } } public void onFeedClick(Feed feed) { startActivity(ItemListActivity.class, feed); } protected List<Tag> getSpecialTags(SQLiteDatabase db) { final List<Tag> specialTags = new ArrayList<Tag>(); if (getApp().getSettings().shouldShowStarredTag()) { final Tag starred = new Tag(); starred.setId(ItemState.STARRED.getId()); starred.setTitle(getString(R.string.tag_starred)); starred.setUnreadCount(itemAdapter.readUnreadCountByLabel(db, starred.getId())); starred.setKey(-1); specialTags.add(starred); } if (getApp().getSettings().shouldShowReadListTag()) { final Tag readList = new Tag(); readList.setId(getApp().getSettings().getLabelReadListId()); readList.setUnreadCount(itemAdapter.readUnreadCountByLabel(db, readList.getId())); readList.setKey(-2); specialTags.add(readList); } if (getApp().getSettings().shouldShowAllItemsTag()) { final Tag allItemsTag = new Tag(); allItemsTag.setId(ItemState.READING_LIST.getId()); allItemsTag.setTitle(getString(R.string.tag_all)); allItemsTag.setUnreadCount(itemAdapter.readUnreadCount(db)); allItemsTag.setFeedFolder(true); allItemsTag.setKey(-4); specialTags.add(allItemsTag); } return specialTags; } /* * action handling */ @Override protected void onRegisterActions() { super.onRegisterActions(); registerAction(R.id.menu_sync_content, new ContentDownloadAction()); fullSyncAction = registerAction(R.id.menu_sync_full, FullSyncAction.class); pushSyncAction = registerAction(R.id.menu_sync_push, PushSyncAction.class); } protected int getItemIndex(ContextMenu.ContextMenuInfo menuInfo) { return (menuInfo instanceof ListView.AdapterContextMenuInfo) ? ((ListView.AdapterContextMenuInfo) menuInfo).position : -1; } protected SortedElement getItem(int itemIndex) { SortedElement element = null; if (itemIndex >= 0 && itemIndex < listAdapter.getCount()) { final ListItem li = (ListItem) listAdapter.getItem(itemIndex); if (li != null && li.getItem() != null) { element = (SortedElement) li.getItem(); } } return element; } protected ContextMenu inflateContextMenu(ContextMenu menu, int menuId, int titleId) { getMenuInflater().inflate(menuId, menu); menu.setHeaderTitle(titleId); return menu; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); if (v.getId() == R.id.tags) { final SortedElement element = getItem(getItemIndex(menuInfo)); if (element instanceof Tag) { final Tag tag = (Tag) element; if ((tag.isUserLabel() && !tag.isFeedFolder()) || ItemState.STARRED.getId().equals(tag.getId())) { inflateContextMenu(menu, R.menu.tag_context, R.string.contextmenu_tag); menu.findItem(R.id.menu_tag_preferences).setIntent(settingsIntentFactory. createElementSettingsIntent(element.getId(), element.getTitle())); } } else if (element instanceof Feed) { inflateContextMenu(menu, R.menu.feed_context, R.string.contextmenu_feed); menu.findItem(R.id.menu_feed_preferences).setIntent(settingsIntentFactory. createElementSettingsIntent(element.getId(), element.getTitle())); } } } /* * event handling */ @Override protected int getOptionsMenuResourceId() { return R.menu.home_options; } @Override protected Class<? extends SettingsHandler> getViewSettingsHandlerClass() { return TagListSettingsHandler.class; } @Override protected void onShowedNoContentPanel() { super.onShowedNoContentPanel(); /* * adjust the no content message */ if (getHideRead()) { /* * register action to show read items */ setNoContentMsg(R.string.no_content_show_read); registerAction(R.id.no_content, new AbstractAction<Application>() { @Override public boolean onFired(ActionContext<? extends Application> applicationActionContext) { setHideRead(false); return true; } }); } else { /* * register action to start sync */ setNoContentMsg(R.string.no_content_sync); registerAction(R.id.no_content, new FullSyncAction(getApp().getSyncService())); } } /* * mark read handling */ @Override protected boolean requiresMarkReadConfirmationDialog() { return getApp().getSettings().confirmMarkAllReadInTagList(); } @Override protected void markAllRead(SQLiteDatabase db) { itemAdapter.markAllRead(db); } /* * hide read handling */ @Override protected boolean getHideRead() { return getApp().getSettings().hideRead(); } @Override protected void setHideReadSetting(boolean hideRead) { getApp().getSettings().setHideRead(hideRead); } /* * sync handling */ @Override public void onSyncStarted() { // nothing to be done } @Override public void onSyncFinished(boolean fullSync, Throwable error) { if (fullSync) { updateView(); } else { /* * only update sync status header */ final ListView listView = getListView(); if (listView.getFirstVisiblePosition() == 0) { final View syncStatusView = listView.getChildAt(0); if (syncStatusView != null) { final HomeListAdapter adapter = (HomeListAdapter) getListView().getAdapter(); if (adapter != null && !adapter.isEmpty() && adapter.getItemViewTypeId(0) == HomeListAdapter.VIEW_TYPE_SYNC_STATUS) { final SyncStatusHeaderViewType syncStatusHeaderViewType = (SyncStatusHeaderViewType) adapter.getViewTypeById(HomeListAdapter.VIEW_TYPE_SYNC_STATUS); syncStatusHeaderViewType.updateView(syncStatusView); } } } } } /* * inner classes */ class DragAndDropOrderComparator implements Comparator<SortedElement> { @Override public int compare(SortedElement o1, SortedElement o2) { int result = o1.getRootSortOrder() - o2.getRootSortOrder(); if (result == 0) { result = o1.getTitle().compareToIgnoreCase(o2.getTitle()); } return result; } } /** * Mimics alphabetical sorting of google reader. Type order is folders, feeds, tags. */ final class AlphabeticalComparator implements Comparator<SortedElement> { private int getElementTypeOrder(SortedElement o) { if (o instanceof Tag) { final Tag t = (Tag) o; return t.isFeedFolder() ? 0 : 2; } else { return 1; } } @Override public int compare(SortedElement o1, SortedElement o2) { int result = getElementTypeOrder(o1) - getElementTypeOrder(o2); if (result == 0) { result = o1.getTitle().compareToIgnoreCase(o2.getTitle()); } return result; } } final class TagListInflator extends ViewOperation<List<HomeListItem>> { protected List<HomeListItem> createItemList(Collection<? extends SortedElement> elements) { final List<HomeListItem> items = new ArrayList<HomeListItem>(elements.size()); for (SortedElement e : elements) { items.add(new HomeListItem(e)); } return items; } @Override protected void onPreFetchData() { super.onPreFetchData(); final SyncService syncService = getApp().getSyncService().getService(); if (syncService != null) { syncService.postProcessSyncIfRequired(); } } @Override protected List<HomeListItem> fetchData(SQLiteDatabase readOnlyDb) { /* * read all tags and feeds */ final List<Tag> tags = getHideRead() ? labelAdapter.readUnreadUserLabels(readOnlyDb) : labelAdapter.readUserLabels(readOnlyDb); final List<Feed> feeds = getHideRead() ? feedAdapter.readUnreadWithoutTag(readOnlyDb) : feedAdapter.readWithoutTag(readOnlyDb); if (tags.isEmpty() && feeds.isEmpty()) { return new ArrayList<HomeListItem>(0); } /* * filter out special tags */ final SortedSet<SortedElement> sortedElements = new TreeSet<SortedElement>( getApp().getSettings().sortByDragAndDropOrder() ? new DragAndDropOrderComparator() : new AlphabeticalComparator()); sortedElements.addAll(TagFilter.filterSpecialTags(getApp().getSettings(), tags)); /* * add all root feeds */ sortedElements.addAll(feeds); /* * add special tags */ final List<Tag> specialTags = getSpecialTags(readOnlyDb); final List<HomeListItem> items = new ArrayList<HomeListItem>(2 + sortedElements.size() + specialTags.size()); if (getApp().getSettings().shouldShowSyncStatus()) { items.add(new HomeListItem(HomeListAdapter.VIEW_TYPE_SYNC_STATUS, -5)); } items.addAll(createItemList(specialTags)); if (getApp().getSettings().shouldShowStarredTag() || getApp().getSettings().shouldShowReadListTag() || getApp().getSettings().shouldShowAllItemsTag()) { items.add(new HomeListItem(HomeListAdapter.VIEW_TYPE_SUBSCRIPTIONS_HEADER, -6)); } items.addAll(createItemList(sortedElements)); return items; } @Override protected boolean updateView(List<HomeListItem> items) { listAdapter.changeCursor(new HomeListItemCursor(items)); return !items.isEmpty(); } } }