public boolean onCreateOptionsMenu(Menu menu) { // If the mode is valid, then set the initial menu if (mMode == ViewMode.UNKNOWN) { return false; } mSearch = menu.findItem(R.id.search); if (mSearch != null) { mSearchWidget = (SearchView) mSearch.getActionView(); mSearch.setOnActionExpandListener(this); SearchManager searchManager = (SearchManager) mActivity.getActivityContext().getSystemService(Context.SEARCH_SERVICE); if (searchManager != null && mSearchWidget != null) { SearchableInfo info = searchManager.getSearchableInfo(mActivity.getComponentName()); mSearchWidget.setSearchableInfo(info); mSearchWidget.setOnQueryTextListener(this); mSearchWidget.setOnSuggestionListener(this); mSearchWidget.setIconifiedByDefault(true); } } mHelpItem = menu.findItem(R.id.help_info_menu_item); mSendFeedbackItem = menu.findItem(R.id.feedback_menu_item); mRefreshItem = menu.findItem(R.id.refresh); mFolderSettingsItem = menu.findItem(R.id.folder_options); mEmptyTrashItem = menu.findItem(R.id.empty_trash); mEmptySpamItem = menu.findItem(R.id.empty_spam); return true; }
@Override public void onViewModeChanged(int newMode) { mMode = newMode; mActivity.invalidateOptionsMenu(); mHandler.removeMessages(SubtitleHandler.EMAIL); // Check if we are either on a phone, or in Conversation mode on tablet. For these, the // recent folders is enabled. switch (mMode) { case ViewMode.UNKNOWN: break; case ViewMode.CONVERSATION_LIST: showNavList(); break; case ViewMode.SEARCH_RESULTS_CONVERSATION: mActionBar.setDisplayHomeAsUpEnabled(true); setEmptyMode(); break; case ViewMode.CONVERSATION: case ViewMode.AD: closeSearchField(); mActionBar.setDisplayHomeAsUpEnabled(true); setEmptyMode(); break; case ViewMode.WAITING_FOR_ACCOUNT_INITIALIZATION: // We want the user to be able to switch accounts while waiting for an account // to sync. showNavList(); break; } }
protected void onConversationSeen() { LogUtils.d(LOG_TAG, "AbstractConversationViewFragment#onConversationSeen()"); // Ignore unsafe calls made after a fragment is detached from an activity final ControllableActivity activity = (ControllableActivity) getActivity(); if (activity == null) { LogUtils.w(LOG_TAG, "ignoring onConversationSeen for conv=%s", mConversation.id); return; } mViewState.setInfoForConversation(mConversation); LogUtils.d( LOG_TAG, "onConversationSeen() - mSuppressMarkingViewed = %b", mSuppressMarkingViewed); // In most circumstances we want to mark the conversation as viewed and read, since the // user has read it. However, if the user has already marked the conversation unread, we // do not want a later mark-read operation to undo this. So we check this variable which // is set in #markUnread() which suppresses automatic mark-read. if (!mSuppressMarkingViewed) { // mark viewed/read if not previously marked viewed by this conversation view, // or if unread messages still exist in the message list cursor // we don't want to keep marking viewed on rotation or restore // but we do want future re-renders to mark read (e.g. "New message from X" case) final MessageCursor cursor = getMessageCursor(); LogUtils.d( LOG_TAG, "onConversationSeen() - mConversation.isViewed() = %b, " + "cursor null = %b, cursor.isConversationRead() = %b", mConversation.isViewed(), cursor == null, cursor != null && cursor.isConversationRead()); if (!mConversation.isViewed() || (cursor != null && !cursor.isConversationRead())) { // Mark the conversation viewed and read. activity .getConversationUpdater() .markConversationsRead(Arrays.asList(mConversation), true, true); // and update the Message objects in the cursor so the next time a cursor update // happens with these messages marked read, we know to ignore it if (cursor != null && !cursor.isClosed()) { cursor.markMessagesRead(); } } } activity.getListHandler().onConversationSeen(); }
// BEGIN conversation header callbacks @Override public void onFoldersClicked() { if (mChangeFoldersMenuItem == null) { LogUtils.e(LOG_TAG, "unable to open 'change folders' dialog for a conversation"); return; } mActivity.onOptionsItemSelected(mChangeFoldersMenuItem); }
public void setBackButton() { if (mActionBar == null) { return; } // Show home as up, and show an icon. final int mask = ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME; mActionBar.setDisplayOptions(mask, mask); mActivity.getActionBar().setHomeButtonEnabled(true); }
/** Removes the back button from being shown */ public void removeBackButton() { if (mActionBar == null) { return; } // Remove the back button but continue showing an icon. final int mask = ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME; mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME, mask); mActivity.getActionBar().setHomeButtonEnabled(false); }
private void updateAccount(Account account) { final boolean accountChanged = mAccount == null || !mAccount.uri.equals(account.uri); mAccount = account; if (mAccount != null && accountChanged) { final ContentResolver resolver = mActivity.getActivityContext().getContentResolver(); final Bundle bundle = new Bundle(1); bundle.putParcelable(UIProvider.SetCurrentAccountColumns.ACCOUNT, account); final UpdateProvider updater = new UpdateProvider(mAccount.uri, resolver); updater.execute(bundle); setFolderAndAccount(false /* folderChanged */); } }
public void initialize( ControllableActivity activity, ActivityController callback, ActionBar actionBar) { mActionBar = actionBar; mController = callback; mActivity = activity; initializeTitleViews(); mFolderObserver = new FolderObserver() { @Override public void onChanged(Folder newFolder) { onFolderUpdated(newFolder); } }; // Return values are purposely discarded. Initialization happens quite early, and we don't // have a valid folder, or a valid list of accounts. mFolderObserver.initialize(mController); updateAccount(mAccountObserver.initialize(activity.getAccountController())); }
/** * Uses the current state to update the current folder {@link #mFolder} and the current account * {@link #mAccount} shown in the actionbar. Also updates the actionbar subtitle to momentarily * display the unread count if it has changed. * * @param folderChanged true if folder changed in terms of URI */ private void setFolderAndAccount(final boolean folderChanged) { // Very little can be done if the actionbar or activity is null. if (mActionBar == null || mActivity == null) { return; } if (ViewMode.isWaitingForSync(mMode)) { // Account is not synced: clear title and update the subtitle. setTitle(""); removeUnreadCount(true); return; } // Check if we should be changing the actionbar at all, and back off if not. final boolean isShowingFolder = mIsOnTablet || ViewMode.isListMode(mMode); if (!isShowingFolder) { // It isn't necessary to set the title in this case, as the title view will // be hidden return; } if (mFolder == null) { // Clear the action bar title. We don't want the app name to be shown while // waiting for the folder query to finish setTitle(""); return; } setTitle(mFolder.name); final int folderUnreadCount = mFolder.isUnreadCountHidden() ? 0 : mFolder.unreadCount; // The user shouldn't see "999+ unread messages", and then a short while later: "999+ // unread messages". So we set our unread count just past the limit. This way we can // change the subtitle the first time around but not for subsequent changes as far as the // unread count remains over the limit. final int toDisplay = (folderUnreadCount > UNREAD_LIMIT) ? (UNREAD_LIMIT + 1) : folderUnreadCount; if ((mUnreadCount != toDisplay || folderChanged) && toDisplay != 0) { setSubtitle(Utils.getUnreadMessageString(mActivity.getApplicationContext(), toDisplay)); } // Schedule a removal of unread count for the future, if there isn't one already. If the // unread count dropped to zero, remove it and show the account name right away. removeUnreadCount(toDisplay == 0); // Remember the new value for the next run mUnreadCount = toDisplay; }
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); final Activity activity = getActivity(); if (!(activity instanceof ControllableActivity)) { LogUtils.wtf( LOG_TAG, "ConversationViewFragment expects only a ControllableActivity to" + "create it. Cannot proceed."); } if (activity == null || activity.isFinishing()) { // Activity is finishing, just bail. return; } mActivity = (ControllableActivity) activity; mContext = activity.getApplicationContext(); mWebViewClient.setActivity(activity); mAccount = mAccountObserver.initialize(mActivity.getAccountController()); mWebViewClient.setAccount(mAccount); }
public ContactLoaderCallbacks getContactInfoSource() { if (mContactLoaderCallbacks == null) { mContactLoaderCallbacks = new ContactLoaderCallbacks(mActivity.getActivityContext()); } return mContactLoaderCallbacks; }
@Override public ConversationUpdater getListController() { final ControllableActivity activity = (ControllableActivity) getActivity(); return activity != null ? activity.getConversationUpdater() : null; }
// We need to do this here instead of in the fragment public void setConversationModeOptions(Menu menu) { if (mCurrentConversation == null) { return; } final boolean showMarkImportant = !mCurrentConversation.isImportant(); Utils.setMenuItemVisibility( menu, R.id.mark_important, showMarkImportant && mAccount.supportsCapability(UIProvider.AccountCapabilities.MARK_IMPORTANT)); Utils.setMenuItemVisibility( menu, R.id.mark_not_important, !showMarkImportant && mAccount.supportsCapability(UIProvider.AccountCapabilities.MARK_IMPORTANT)); final boolean showDelete = mFolder != null && mFolder.supportsCapability(UIProvider.FolderCapabilities.DELETE); Utils.setMenuItemVisibility(menu, R.id.delete, showDelete); // We only want to show the discard drafts menu item if we are not showing the delete menu // item, and the current folder is a draft folder and the account supports discarding // drafts for a conversation final boolean showDiscardDrafts = !showDelete && mFolder != null && mFolder.isDraft() && mAccount.supportsCapability(AccountCapabilities.DISCARD_CONVERSATION_DRAFTS); Utils.setMenuItemVisibility(menu, R.id.discard_drafts, showDiscardDrafts); final boolean archiveVisible = mAccount.supportsCapability(AccountCapabilities.ARCHIVE) && mFolder != null && mFolder.supportsCapability(FolderCapabilities.ARCHIVE) && !mFolder.isTrash(); Utils.setMenuItemVisibility(menu, R.id.archive, archiveVisible); Utils.setMenuItemVisibility( menu, R.id.remove_folder, !archiveVisible && mFolder != null && mFolder.supportsCapability(FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES) && !mFolder.isProviderFolder() && mAccount.supportsCapability(AccountCapabilities.ARCHIVE)); Utils.setMenuItemVisibility( menu, R.id.move_to, mFolder != null && mFolder.supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION)); Utils.setMenuItemVisibility( menu, R.id.move_to_inbox, mFolder != null && mFolder.supportsCapability(FolderCapabilities.ALLOWS_MOVE_TO_INBOX)); final MenuItem removeFolder = menu.findItem(R.id.remove_folder); if (mFolder != null && removeFolder != null) { removeFolder.setTitle( mActivity.getApplicationContext().getString(R.string.remove_folder, mFolder.name)); } Utils.setMenuItemVisibility( menu, R.id.report_spam, mAccount.supportsCapability(AccountCapabilities.REPORT_SPAM) && mFolder != null && mFolder.supportsCapability(FolderCapabilities.REPORT_SPAM) && !mCurrentConversation.spam); Utils.setMenuItemVisibility( menu, R.id.mark_not_spam, mAccount.supportsCapability(AccountCapabilities.REPORT_SPAM) && mFolder != null && mFolder.supportsCapability(FolderCapabilities.MARK_NOT_SPAM) && mCurrentConversation.spam); Utils.setMenuItemVisibility( menu, R.id.report_phishing, mAccount.supportsCapability(AccountCapabilities.REPORT_PHISHING) && mFolder != null && mFolder.supportsCapability(FolderCapabilities.REPORT_PHISHING) && !mCurrentConversation.phishing); Utils.setMenuItemVisibility( menu, R.id.mute, mAccount.supportsCapability(AccountCapabilities.MUTE) && mFolder != null && mFolder.supportsCapability(FolderCapabilities.DESTRUCTIVE_MUTE) && !mCurrentConversation.muted); }