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.VISIBLE); 104 mNetworkError.setVisibility(View.GONE); 105 mLoadMore.setVisibility(View.GONE); 106 return true; 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 if (UIProvider.CursorStatus.isWaitingForResults(cursorStatus)) { 116 mLoading.setVisibility(View.VISIBLE); 117 mNetworkError.setVisibility(View.GONE); 118 mLoadMore.setVisibility(View.GONE); 119 } else if (mErrorStatus != UIProvider.LastSyncResult.SUCCESS) { 120 mNetworkError.setVisibility(View.VISIBLE); 121 mErrorText.setText(Utils.getSyncStatusText(getContext(), mErrorStatus)); 122 mLoading.setVisibility(View.GONE); 123 mLoadMore.setVisibility(View.GONE); 124 // Only show the "Retry" button for I/O errors; it won't help for 125 // internal errors. 126 mErrorActionButton.setVisibility( 127 mErrorStatus != UIProvider.LastSyncResult.SECURITY_ERROR ? 128 View.VISIBLE : View.GONE); 129 130 final int actionTextResourceId; 131 switch (mErrorStatus) { 132 case UIProvider.LastSyncResult.CONNECTION_ERROR: 133 actionTextResourceId = R.string.retry; 134 break; 135 case UIProvider.LastSyncResult.AUTH_ERROR: 136 actionTextResourceId = R.string.signin; 137 break; 138 case UIProvider.LastSyncResult.SECURITY_ERROR: 139 actionTextResourceId = R.string.retry; 140 mNetworkError.setVisibility(View.GONE); 141 break; // Currently we do nothing for security errors. 142 case UIProvider.LastSyncResult.STORAGE_ERROR: 143 actionTextResourceId = R.string.info; 144 break; 145 case UIProvider.LastSyncResult.INTERNAL_ERROR: 146 actionTextResourceId = R.string.report; 147 break; 148 default: 149 actionTextResourceId = R.string.retry; 150 mNetworkError.setVisibility(View.GONE); 151 break; 152 } 153 mErrorActionButton.setText(actionTextResourceId); 154 155 } else if (mLoadMoreUri != null && cursor.getCount() < totalCount) { 156 mLoading.setVisibility(View.GONE); 157 mNetworkError.setVisibility(View.GONE); 158 mLoadMore.setVisibility(View.VISIBLE); 159 } else { 160 showFooter = false; 161 } 162 return showFooter; 163 } 164 165 /** 166 * Update to the appropriate background when the view mode changes. 167 */ 168 @Override 169 public void onViewModeChanged(int newMode) { 170 final Drawable drawable; 171 if (mTabletDevice && newMode == ViewMode.CONVERSATION_LIST) { 172 drawable = getWideBackground(); 173 } else { 174 drawable = getNormalBackground(); 175 } 176 setBackgroundDrawable(drawable); 177 } 178 179 private Drawable getWideBackground() { 180 if (sWideBackground == null) { 181 sWideBackground = getBackground(R.drawable.conversation_wide_unread_selector); 182 } 183 return sWideBackground; 184 } 185 186 private Drawable getNormalBackground() { 187 if (sNormalBackground == null) { 188 sNormalBackground = getBackground(R.drawable.conversation_unread_selector); 189 } 190 return sNormalBackground; 191 } 192 193 private Drawable getBackground(int resId) { 194 return getContext().getResources().getDrawable(resId); 195 } 196 } 197