Home | History | Annotate | Download | only in browse
      1 /*
      2  * Copyright (C) 2012 Google Inc.
      3  * Licensed to The Android Open Source Project.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.mail.browse;
     19 
     20 import android.content.Context;
     21 import android.graphics.drawable.Drawable;
     22 import android.net.Uri;
     23 import android.os.Bundle;
     24 import android.util.AttributeSet;
     25 import android.view.View;
     26 import android.widget.Button;
     27 import android.widget.LinearLayout;
     28 import android.widget.TextView;
     29 
     30 import com.android.mail.R;
     31 import com.android.mail.providers.Folder;
     32 import com.android.mail.providers.UIProvider;
     33 import com.android.mail.ui.ViewMode;
     34 import com.android.mail.utils.Utils;
     35 
     36 public final class ConversationListFooterView extends LinearLayout implements View.OnClickListener,
     37         ViewMode.ModeChangeListener {
     38 
     39     public interface FooterViewClickListener {
     40         void onFooterViewErrorActionClick(Folder folder, int errorStatus);
     41         void onFooterViewLoadMoreClick(Folder folder);
     42     }
     43 
     44     private View mLoading;
     45     private View mNetworkError;
     46     private View mLoadMore;
     47     private Button mErrorActionButton;
     48     private TextView mErrorText;
     49     private Folder mFolder;
     50     private Uri mLoadMoreUri;
     51     private int mErrorStatus;
     52     private FooterViewClickListener mClickListener;
     53     private final boolean mTabletDevice;
     54     // Backgrounds for different states.
     55     private static Drawable sWideBackground;
     56     private static Drawable sNormalBackground;
     57 
     58     public ConversationListFooterView(Context context, AttributeSet attrs) {
     59         super(context, attrs);
     60         mTabletDevice = Utils.useTabletUI(context.getResources());
     61     }
     62 
     63     @Override
     64     protected void onFinishInflate() {
     65         super.onFinishInflate();
     66 
     67         mLoading = findViewById(R.id.loading);
     68         mNetworkError = findViewById(R.id.network_error);
     69         mLoadMore = findViewById(R.id.load_more);
     70         mLoadMore.setOnClickListener(this);
     71         mErrorActionButton = (Button) findViewById(R.id.error_action_button);
     72         mErrorActionButton.setOnClickListener(this);
     73         mErrorText = (TextView)findViewById(R.id.error_text);
     74     }
     75 
     76     public void setClickListener(FooterViewClickListener listener) {
     77         mClickListener = listener;
     78     }
     79 
     80     @Override
     81     public void onClick(View v) {
     82         final int id = v.getId();
     83         final Folder f = (Folder) v.getTag();
     84         if (id == R.id.error_action_button) {
     85             mClickListener.onFooterViewErrorActionClick(f, mErrorStatus);
     86         } else if (id == R.id.load_more) {
     87             mClickListener.onFooterViewLoadMoreClick(f);
     88         }
     89     }
     90 
     91     public void setFolder(Folder folder) {
     92         mFolder = folder;
     93         mErrorActionButton.setTag(mFolder);
     94         mLoadMore.setTag(mFolder);
     95         mLoadMoreUri = folder.loadMoreUri;
     96     }
     97 
     98     /**
     99      * Update the view to reflect the new folder status.
    100      */
    101     public boolean updateStatus(final ConversationCursor cursor) {
    102         if (cursor == null) {
    103             mLoading.setVisibility(View.GONE);
    104             mNetworkError.setVisibility(View.GONE);
    105             mLoadMore.setVisibility(View.GONE);
    106             return false;
    107         }
    108         boolean showFooter = true;
    109         final Bundle extras = cursor.getExtras();
    110         final int cursorStatus = extras.getInt(UIProvider.CursorExtraKeys.EXTRA_STATUS);
    111         mErrorStatus = extras.containsKey(UIProvider.CursorExtraKeys.EXTRA_ERROR) ?
    112                 extras.getInt(UIProvider.CursorExtraKeys.EXTRA_ERROR)
    113                 : UIProvider.LastSyncResult.SUCCESS;
    114         final int totalCount = extras.getInt(UIProvider.CursorExtraKeys.EXTRA_TOTAL_COUNT);
    115 
    116         if (UIProvider.CursorStatus.isWaitingForResults(cursorStatus)) {
    117             if (cursor.getCount() != 0) {
    118                 // When loading more, show the spinner in the footer.
    119                 mLoading.setVisibility(View.VISIBLE);
    120                 mNetworkError.setVisibility(View.GONE);
    121                 mLoadMore.setVisibility(View.GONE);
    122             } else {
    123                 // We're currently loading, but we have no messages at all. We don't need to show
    124                 // the footer, because we should be displaying the loading state on the
    125                 // conversation list itself.
    126                 showFooter = false;
    127             }
    128         } else if (mErrorStatus != UIProvider.LastSyncResult.SUCCESS) {
    129             // We are in some error state, show the footer with an error message.
    130             mNetworkError.setVisibility(View.VISIBLE);
    131             mErrorText.setText(Utils.getSyncStatusText(getContext(), mErrorStatus));
    132             mLoading.setVisibility(View.GONE);
    133             mLoadMore.setVisibility(View.GONE);
    134             // Only show the "Retry" button for I/O errors; it won't help for
    135             // internal errors.
    136             mErrorActionButton.setVisibility(
    137                     mErrorStatus != UIProvider.LastSyncResult.SECURITY_ERROR ?
    138                     View.VISIBLE : View.GONE);
    139 
    140             final int actionTextResourceId;
    141             switch (mErrorStatus) {
    142                 case UIProvider.LastSyncResult.CONNECTION_ERROR:
    143                     actionTextResourceId = R.string.retry;
    144                     break;
    145                 case UIProvider.LastSyncResult.SERVER_ERROR:
    146                     actionTextResourceId = R.string.retry;
    147                     break;
    148                 case UIProvider.LastSyncResult.AUTH_ERROR:
    149                     actionTextResourceId = R.string.signin;
    150                     break;
    151                 case UIProvider.LastSyncResult.SECURITY_ERROR:
    152                     actionTextResourceId = R.string.retry;
    153                     mNetworkError.setVisibility(View.GONE);
    154                     break; // Currently we do nothing for security errors.
    155                 case UIProvider.LastSyncResult.STORAGE_ERROR:
    156                     actionTextResourceId = R.string.info;
    157                     break;
    158                 case UIProvider.LastSyncResult.INTERNAL_ERROR:
    159                     actionTextResourceId = R.string.report;
    160                     break;
    161                 default:
    162                     actionTextResourceId = R.string.retry;
    163                     mNetworkError.setVisibility(View.GONE);
    164                     break;
    165             }
    166             mErrorActionButton.setText(actionTextResourceId);
    167 
    168         } else if (mLoadMoreUri != null && cursor.getCount() < totalCount) {
    169             // We know that there are more messages on the server than we have locally, so we
    170             // need to show the footer with the "load more" button.
    171             mLoading.setVisibility(View.GONE);
    172             mNetworkError.setVisibility(View.GONE);
    173             mLoadMore.setVisibility(View.VISIBLE);
    174         } else {
    175             showFooter = false;
    176         }
    177         return showFooter;
    178     }
    179 
    180     /**
    181      * Update to the appropriate background when the view mode changes.
    182      */
    183     @Override
    184     public void onViewModeChanged(int newMode) {
    185         final Drawable drawable;
    186         if (mTabletDevice && newMode == ViewMode.CONVERSATION_LIST) {
    187             drawable = getWideBackground();
    188         } else {
    189             drawable = getNormalBackground();
    190         }
    191         setBackgroundDrawable(drawable);
    192     }
    193 
    194     private Drawable getWideBackground() {
    195         if (sWideBackground == null) {
    196             sWideBackground = getBackground(R.drawable.conversation_wide_unread_selector);
    197         }
    198         return sWideBackground;
    199     }
    200 
    201     private Drawable getNormalBackground() {
    202         if (sNormalBackground == null) {
    203             sNormalBackground = getBackground(R.drawable.conversation_item_background_selector);
    204         }
    205         return sNormalBackground;
    206     }
    207 
    208     private Drawable getBackground(int resId) {
    209         return getContext().getResources().getDrawable(resId);
    210     }
    211 }
    212