• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
onFooterViewErrorActionClick(Folder folder, int errorStatus)40         void onFooterViewErrorActionClick(Folder folder, int errorStatus);
onFooterViewLoadMoreClick(Folder folder)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 
ConversationListFooterView(Context context, AttributeSet attrs)58     public ConversationListFooterView(Context context, AttributeSet attrs) {
59         super(context, attrs);
60         mTabletDevice = Utils.useTabletUI(context.getResources());
61     }
62 
63     @Override
onFinishInflate()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 
setClickListener(FooterViewClickListener listener)76     public void setClickListener(FooterViewClickListener listener) {
77         mClickListener = listener;
78     }
79 
80     @Override
onClick(View v)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 
setFolder(Folder folder)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      */
updateStatus(final ConversationCursor cursor)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
onViewModeChanged(int newMode)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 
getWideBackground()194     private Drawable getWideBackground() {
195         if (sWideBackground == null) {
196             sWideBackground = getBackground(R.drawable.conversation_wide_unread_selector);
197         }
198         return sWideBackground;
199     }
200 
getNormalBackground()201     private Drawable getNormalBackground() {
202         if (sNormalBackground == null) {
203             sNormalBackground = getBackground(R.drawable.conversation_item_background_selector);
204         }
205         return sNormalBackground;
206     }
207 
getBackground(int resId)208     private Drawable getBackground(int resId) {
209         return getContext().getResources().getDrawable(resId);
210     }
211 }
212