1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.dashboard; 17 18 import android.accounts.Account; 19 import android.annotation.DrawableRes; 20 import android.annotation.LayoutRes; 21 import android.annotation.StringRes; 22 import android.app.Activity; 23 import android.app.DialogFragment; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.os.Bundle; 28 import android.support.v7.widget.RecyclerView; 29 import android.text.TextUtils; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.AdapterView; 34 import android.widget.ArrayAdapter; 35 import android.widget.ImageView; 36 import android.widget.Spinner; 37 import android.widget.TextView; 38 39 import com.android.internal.logging.MetricsLogger; 40 import com.android.internal.logging.MetricsProto; 41 import com.android.settings.R; 42 import com.android.settings.overlay.SupportFeatureProvider; 43 import com.android.settings.support.SupportDisclaimerDialogFragment; 44 import com.android.settings.support.SupportPhone; 45 import com.android.settings.support.SupportPhoneDialogFragment; 46 47 import java.util.ArrayList; 48 import java.util.List; 49 import java.util.Objects; 50 51 import static com.android.settings.overlay.SupportFeatureProvider.SupportType.CHAT; 52 import static com.android.settings.overlay.SupportFeatureProvider.SupportType.PHONE; 53 54 /** 55 * Item adapter for support tiles. 56 */ 57 public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAdapter.ViewHolder> { 58 59 private static final String STATE_SELECTED_COUNTRY = "STATE_SELECTED_COUNTRY"; 60 private static final int TYPE_ESCALATION_OPTIONS = R.layout.support_escalation_options; 61 private static final int TYPE_ESCALATION_OPTIONS_OFFLINE = 62 R.layout.support_offline_escalation_options; 63 private static final int TYPE_SUPPORT_TILE = R.layout.support_tile; 64 private static final int TYPE_SUPPORT_TILE_SPACER = R.layout.support_tile_spacer; 65 private static final int TYPE_SIGN_IN_BUTTON = R.layout.support_sign_in_button; 66 67 private final Activity mActivity; 68 private final EscalationClickListener mEscalationClickListener; 69 private final SpinnerItemSelectListener mSpinnerItemSelectListener; 70 private final SupportFeatureProvider mSupportFeatureProvider; 71 private final View.OnClickListener mItemClickListener; 72 private final List<SupportData> mSupportData; 73 74 private String mSelectedCountry; 75 private boolean mHasInternet; 76 private Account mAccount; 77 SupportItemAdapter(Activity activity, Bundle savedInstanceState, SupportFeatureProvider supportFeatureProvider, View.OnClickListener itemClickListener)78 public SupportItemAdapter(Activity activity, Bundle savedInstanceState, 79 SupportFeatureProvider supportFeatureProvider, View.OnClickListener itemClickListener) { 80 mActivity = activity; 81 mSupportFeatureProvider = supportFeatureProvider; 82 mItemClickListener = itemClickListener; 83 mEscalationClickListener = new EscalationClickListener(); 84 mSpinnerItemSelectListener = new SpinnerItemSelectListener(); 85 mSupportData = new ArrayList<>(); 86 // Optimistically assume we have Internet access. It will be updated later to correct value. 87 mHasInternet = true; 88 if (savedInstanceState != null) { 89 mSelectedCountry = savedInstanceState.getString(STATE_SELECTED_COUNTRY); 90 } else { 91 mSelectedCountry = mSupportFeatureProvider.getCurrentCountryCodeIfHasConfig(PHONE); 92 } 93 mAccount = mSupportFeatureProvider.getSupportEligibleAccount(mActivity); 94 refreshData(); 95 } 96 97 @Override onCreateViewHolder(ViewGroup parent, int viewType)98 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 99 return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate( 100 viewType, parent, false)); 101 } 102 103 @Override onBindViewHolder(ViewHolder holder, int position)104 public void onBindViewHolder(ViewHolder holder, int position) { 105 final SupportData data = mSupportData.get(position); 106 switch (holder.getItemViewType()) { 107 case TYPE_SIGN_IN_BUTTON: 108 bindSignInPromoTile(holder, (EscalationData) data); 109 break; 110 case TYPE_ESCALATION_OPTIONS: 111 bindEscalationOptions(holder, (EscalationData) data); 112 break; 113 case TYPE_ESCALATION_OPTIONS_OFFLINE: 114 bindOfflineEscalationOptions(holder, (OfflineEscalationData) data); 115 break; 116 case TYPE_SUPPORT_TILE_SPACER: 117 break; 118 default: 119 bindSupportTile(holder, data); 120 break; 121 } 122 } 123 124 @Override getItemViewType(int position)125 public int getItemViewType(int position) { 126 return mSupportData.get(position).type; 127 } 128 129 @Override getItemCount()130 public int getItemCount() { 131 return mSupportData.size(); 132 } 133 134 /** 135 * Called when a support item is clicked. 136 */ onItemClicked(int position)137 public void onItemClicked(int position) { 138 if (position >= 0 && position < mSupportData.size()) { 139 final SupportData data = mSupportData.get(position); 140 if (data.intent != null && 141 mActivity.getPackageManager().resolveActivity(data.intent, 0) != null) { 142 if (data.metricsEvent >= 0) { 143 MetricsLogger.action(mActivity, data.metricsEvent); 144 } 145 mActivity.startActivityForResult(data.intent, 0); 146 } 147 } 148 } 149 setHasInternet(boolean hasInternet)150 public void setHasInternet(boolean hasInternet) { 151 if (mHasInternet != hasInternet) { 152 mHasInternet = hasInternet; 153 refreshEscalationCards(); 154 } 155 } 156 setAccount(Account account)157 public void setAccount(Account account) { 158 if (!Objects.equals(mAccount, account)) { 159 mAccount = account; 160 mSupportFeatureProvider.refreshOperationRules(); 161 refreshEscalationCards(); 162 } 163 } 164 onSaveInstanceState(Bundle outState)165 public void onSaveInstanceState(Bundle outState) { 166 outState.putString(STATE_SELECTED_COUNTRY, mSelectedCountry); 167 } 168 169 /** 170 * Create data for the adapter. If there is already data in the adapter, they will be 171 * destroyed and recreated. 172 */ refreshData()173 private void refreshData() { 174 mSupportData.clear(); 175 addEscalationCards(); 176 addMoreHelpItems(); 177 notifyDataSetChanged(); 178 } 179 180 /** 181 * Adds 1 escalation card. Based on current phone state, the escalation card can display 182 * different content. 183 */ addEscalationCards()184 private void addEscalationCards() { 185 if (mAccount == null) { 186 addSignInPromo(); 187 } else if (mHasInternet) { 188 addOnlineEscalationCards(); 189 } else { 190 addOfflineEscalationCards(); 191 } 192 } 193 194 /** 195 * Finds and refreshes escalation card data. 196 */ refreshEscalationCards()197 private void refreshEscalationCards() { 198 if (getItemCount() > 0) { 199 final int itemType = getItemViewType(0 /* position */); 200 if (itemType == TYPE_SIGN_IN_BUTTON 201 || itemType == TYPE_ESCALATION_OPTIONS 202 || itemType == TYPE_ESCALATION_OPTIONS_OFFLINE) { 203 mSupportData.remove(0 /* position */); 204 addEscalationCards(); 205 notifyItemChanged(0 /* position */); 206 } 207 } 208 } 209 addOnlineEscalationCards()210 private void addOnlineEscalationCards() { 211 final boolean hasPhoneOperation = 212 mSupportFeatureProvider.isSupportTypeEnabled(mActivity, PHONE); 213 final boolean hasChatOperation = 214 mSupportFeatureProvider.isSupportTypeEnabled(mActivity, CHAT); 215 final EscalationData.Builder builder = new EscalationData.Builder(mActivity); 216 if (!hasPhoneOperation && !hasChatOperation) { 217 // No support at all. 218 builder.setTileTitle(R.string.support_escalation_title) 219 .setTileSummary(R.string.support_escalation_unavailable_summary); 220 } else if (mSupportFeatureProvider.isAlwaysOperating(PHONE, null /* countryCode */) 221 || mSupportFeatureProvider.isAlwaysOperating(CHAT, null /* countryCode */)) { 222 // Support is available. 223 builder.setTileTitle(R.string.support_escalation_24_7_title) 224 .setTileTitleDescription(R.string.support_escalation_24_7_content_description) 225 .setTileSummary(mActivity.getString(R.string.support_escalation_24_7_summary)); 226 } else if (mSupportFeatureProvider.isOperatingNow(PHONE) 227 || mSupportFeatureProvider.isOperatingNow(CHAT)) { 228 // Support is available now. 229 builder.setTileTitle(R.string.support_escalation_title) 230 .setTileSummary(R.string.support_escalation_summary); 231 } else { 232 // Support is now temporarily unavailable. 233 builder.setTileTitle(R.string.support_escalation_title) 234 .setTileSummary( 235 mSupportFeatureProvider.getOperationHours(mActivity, PHONE, null, 236 true /* hasInternet */)); 237 } 238 if (hasPhoneOperation) { 239 builder.setText1(R.string.support_escalation_by_phone) 240 .setSummary1(mSupportFeatureProvider.getEstimatedWaitTime(mActivity, PHONE)) 241 .setEnabled1(mSupportFeatureProvider.isOperatingNow(PHONE)); 242 } 243 if (hasChatOperation) { 244 builder.setText2(R.string.support_escalation_by_chat) 245 .setSummary2(mSupportFeatureProvider.getEstimatedWaitTime(mActivity, CHAT)) 246 .setEnabled2(mSupportFeatureProvider.isOperatingNow(CHAT)); 247 } 248 mSupportData.add(0 /* index */, builder.build()); 249 } 250 addOfflineEscalationCards()251 private void addOfflineEscalationCards() { 252 final CharSequence operatingHours; 253 final boolean isPhoneSupportAlwaysOperating = 254 mSupportFeatureProvider.isAlwaysOperating(PHONE, mSelectedCountry); 255 if (isPhoneSupportAlwaysOperating) { 256 operatingHours = mActivity.getString(R.string.support_escalation_24_7_summary); 257 } else { 258 operatingHours = mSupportFeatureProvider.getOperationHours(mActivity, 259 PHONE, mSelectedCountry, false /* hasInternet */); 260 } 261 mSupportData.add(0 /* index */, new OfflineEscalationData.Builder(mActivity) 262 .setCountries(mSupportFeatureProvider.getPhoneSupportCountries()) 263 .setTollFreePhone(mSupportFeatureProvider.getSupportPhones( 264 mSelectedCountry, true /* isTollFree */)) 265 .setTolledPhone(mSupportFeatureProvider.getSupportPhones( 266 mSelectedCountry, false /* isTollFree */)) 267 .setTileTitle(isPhoneSupportAlwaysOperating 268 ? R.string.support_escalation_24_7_title 269 : R.string.support_escalation_title) 270 .setTileTitleDescription(isPhoneSupportAlwaysOperating 271 ? R.string.support_escalation_24_7_content_description 272 : R.string.support_escalation_title) 273 .setTileSummary(operatingHours) 274 .build()); 275 } 276 addSignInPromo()277 private void addSignInPromo() { 278 mSupportData.add(0 /* index */, new EscalationData.Builder(mActivity, TYPE_SIGN_IN_BUTTON) 279 .setText1(R.string.support_sign_in_button_text) 280 .setText2(R.string.support_sign_in_required_help) 281 .setTileTitle(R.string.support_sign_in_required_title) 282 .setTileSummary(R.string.support_sign_in_required_summary) 283 .build()); 284 } 285 addMoreHelpItems()286 private void addMoreHelpItems() { 287 mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE_SPACER).build()); 288 PackageManager packageManager = mActivity.getPackageManager(); 289 Intent intent = mSupportFeatureProvider.getHelpIntent(mActivity); 290 if (packageManager.resolveActivity(intent, 0) != null) { 291 mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE) 292 .setIcon(R.drawable.ic_help_24dp) 293 .setTileTitle(R.string.support_help_feedback_title) 294 .setIntent(intent) 295 .setMetricsEvent(MetricsProto.MetricsEvent.ACTION_SUPPORT_HELP_AND_FEEDBACK) 296 .build()); 297 } 298 intent = mSupportFeatureProvider.getTipsAndTricksIntent(mActivity); 299 if (packageManager.resolveActivity(intent, 0) != null) { 300 mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE) 301 .setIcon(R.drawable.ic_lightbulb_outline_24) 302 .setTileTitle(R.string.support_tips_and_tricks_title) 303 .setIntent(intent) 304 .setMetricsEvent(MetricsProto.MetricsEvent.ACTION_SUPPORT_TIPS_AND_TRICKS) 305 .build()); 306 } 307 } 308 bindEscalationOptions(ViewHolder holder, EscalationData data)309 private void bindEscalationOptions(ViewHolder holder, EscalationData data) { 310 holder.tileTitleView.setText(data.tileTitle); 311 holder.tileTitleView.setContentDescription(data.tileTitleDescription); 312 holder.tileSummaryView.setText(data.tileSummary); 313 if (data.text1 == 0) { 314 holder.text1View.setVisibility(View.GONE); 315 } else { 316 holder.text1View.setText(data.text1); 317 holder.text1View.setOnClickListener(mEscalationClickListener); 318 holder.text1View.setEnabled(data.enabled1 && mHasInternet); 319 holder.text1View.setVisibility(View.VISIBLE); 320 } 321 if (TextUtils.isEmpty(data.text2)) { 322 holder.text2View.setVisibility(View.GONE); 323 } else { 324 holder.text2View.setText(data.text2); 325 holder.text2View.setOnClickListener(mEscalationClickListener); 326 holder.text2View.setEnabled(data.enabled2 && mHasInternet); 327 holder.text2View.setVisibility(View.VISIBLE); 328 } 329 if (holder.summary1View != null) { 330 holder.summary1View.setText(data.summary1); 331 holder.summary1View.setVisibility(mHasInternet && !TextUtils.isEmpty(data.summary1) 332 ? View.VISIBLE : View.GONE); 333 } 334 if (holder.summary2View != null) { 335 holder.summary2View.setText(data.summary2); 336 holder.summary2View.setVisibility(mHasInternet && !TextUtils.isEmpty(data.summary2) 337 ? View.VISIBLE : View.GONE); 338 } 339 } 340 bindOfflineEscalationOptions(ViewHolder holder, OfflineEscalationData data)341 private void bindOfflineEscalationOptions(ViewHolder holder, OfflineEscalationData data) { 342 // Bind Title 343 holder.tileTitleView.setText(data.tileTitle); 344 holder.tileTitleView.setContentDescription(data.tileTitleDescription); 345 holder.tileSummaryView.setText(data.tileSummary); 346 // Bind spinner 347 final Spinner spinner = (Spinner) holder.itemView.findViewById(R.id.spinner); 348 final ArrayAdapter<String> adapter = new ArrayAdapter( 349 mActivity, android.R.layout.simple_spinner_dropdown_item, data.countries); 350 spinner.setAdapter(adapter); 351 final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes(); 352 for (int i = 0; i < countryCodes.size(); i++) { 353 if (TextUtils.equals(countryCodes.get(i), mSelectedCountry)) { 354 spinner.setSelection(i); 355 break; 356 } 357 } 358 spinner.setOnItemSelectedListener(mSpinnerItemSelectListener); 359 // Bind buttons 360 if (data.tollFreePhone != null) { 361 holder.text1View.setText(data.tollFreePhone.number); 362 holder.text1View.setVisibility(View.VISIBLE); 363 holder.text1View.setOnClickListener(mEscalationClickListener); 364 } else { 365 holder.text1View.setVisibility(View.GONE); 366 } 367 if (data.tolledPhone != null) { 368 holder.text2View.setText( 369 mActivity.getString(R.string.support_international_phone_title)); 370 holder.text2View.setVisibility(View.VISIBLE); 371 holder.text2View.setOnClickListener(mEscalationClickListener); 372 } else { 373 holder.text2View.setVisibility(View.GONE); 374 } 375 } 376 bindSignInPromoTile(ViewHolder holder, EscalationData data)377 private void bindSignInPromoTile(ViewHolder holder, EscalationData data) { 378 holder.tileTitleView.setText(data.tileTitle); 379 holder.tileTitleView.setContentDescription(data.tileTitleDescription); 380 holder.tileSummaryView.setText(data.tileSummary); 381 holder.text1View.setText(data.text1); 382 holder.text2View.setText(data.text2); 383 holder.text1View.setOnClickListener(mEscalationClickListener); 384 holder.text2View.setOnClickListener(mEscalationClickListener); 385 } 386 bindSupportTile(ViewHolder holder, SupportData data)387 private void bindSupportTile(ViewHolder holder, SupportData data) { 388 if (holder.iconView != null) { 389 holder.iconView.setImageResource(data.icon); 390 } 391 if (holder.tileTitleView != null) { 392 holder.tileTitleView.setText(data.tileTitle); 393 holder.tileTitleView.setContentDescription(data.tileTitleDescription); 394 } 395 if (holder.tileSummaryView != null) { 396 holder.tileSummaryView.setText(data.tileSummary); 397 } 398 holder.itemView.setOnClickListener(mItemClickListener); 399 } 400 401 /** 402 * Show a disclaimer dialog and start support action after disclaimer has been acknowledged. 403 */ tryStartDisclaimerAndSupport(final @SupportFeatureProvider.SupportType int type)404 private void tryStartDisclaimerAndSupport(final @SupportFeatureProvider.SupportType int type) { 405 if (mSupportFeatureProvider.shouldShowDisclaimerDialog(mActivity)) { 406 DialogFragment fragment = SupportDisclaimerDialogFragment.newInstance(mAccount, type); 407 fragment.show(mActivity.getFragmentManager(), SupportDisclaimerDialogFragment.TAG); 408 return; 409 } 410 mSupportFeatureProvider.startSupport(mActivity, mAccount, type); 411 } 412 413 /** 414 * Click handler for starting escalation options. 415 */ 416 private final class EscalationClickListener implements View.OnClickListener { 417 @Override onClick(final View v)418 public void onClick(final View v) { 419 if (mAccount == null) { 420 switch (v.getId()) { 421 case android.R.id.text1: 422 MetricsLogger.action(mActivity, 423 MetricsProto.MetricsEvent.ACTION_SUPPORT_SIGN_IN); 424 mActivity.startActivityForResult( 425 mSupportFeatureProvider.getAccountLoginIntent(), 426 0 /* requestCode */); 427 break; 428 case android.R.id.text2: 429 mActivity.startActivityForResult( 430 mSupportFeatureProvider.getSignInHelpIntent(mActivity), 431 0 /* requestCode */); 432 break; 433 } 434 } else if (mHasInternet) { 435 switch (v.getId()) { 436 case android.R.id.text1: 437 MetricsLogger.action(mActivity, 438 MetricsProto.MetricsEvent.ACTION_SUPPORT_PHONE); 439 tryStartDisclaimerAndSupport(PHONE); 440 break; 441 case android.R.id.text2: 442 MetricsLogger.action(mActivity, 443 MetricsProto.MetricsEvent.ACTION_SUPPORT_CHAT); 444 tryStartDisclaimerAndSupport(CHAT); 445 break; 446 } 447 } else { 448 switch (v.getId()) { 449 case android.R.id.text1: { 450 final SupportPhone phone = mSupportFeatureProvider 451 .getSupportPhones(mSelectedCountry, true /* isTollFree */); 452 if (phone != null) { 453 final Intent intent = phone.getDialIntent(); 454 final boolean canDial = !mActivity.getPackageManager() 455 .queryIntentActivities(intent, 0) 456 .isEmpty(); 457 if (canDial) { 458 MetricsLogger.action(mActivity, 459 MetricsProto.MetricsEvent.ACTION_SUPPORT_DAIL_TOLLFREE); 460 mActivity.startActivity(intent); 461 } 462 } 463 break; 464 } 465 case android.R.id.text2: { 466 final SupportPhone phone = mSupportFeatureProvider 467 .getSupportPhones(mSelectedCountry, false /* isTollFree */); 468 final SupportPhoneDialogFragment fragment = 469 SupportPhoneDialogFragment.newInstance(phone); 470 MetricsLogger.action(mActivity, 471 MetricsProto.MetricsEvent.ACTION_SUPPORT_VIEW_TRAVEL_ABROAD_DIALOG); 472 fragment.show(mActivity.getFragmentManager(), 473 SupportPhoneDialogFragment.TAG); 474 break; 475 } 476 } 477 } 478 } 479 } 480 481 private final class SpinnerItemSelectListener implements AdapterView.OnItemSelectedListener { 482 483 @Override onItemSelected(AdapterView<?> parent, View view, int position, long id)484 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 485 final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes(); 486 final String selectedCountry = countryCodes.get(position); 487 if (!TextUtils.equals(selectedCountry, mSelectedCountry)) { 488 mSelectedCountry = selectedCountry; 489 refreshEscalationCards(); 490 } 491 } 492 493 @Override onNothingSelected(AdapterView<?> parent)494 public void onNothingSelected(AdapterView<?> parent) { 495 // Do nothing. 496 } 497 } 498 499 /** 500 * {@link RecyclerView.ViewHolder} for support items. 501 */ 502 static final class ViewHolder extends RecyclerView.ViewHolder { 503 504 final ImageView iconView; 505 final TextView tileTitleView; 506 final TextView tileSummaryView; 507 final TextView text1View; 508 final TextView text2View; 509 final TextView summary1View; 510 final TextView summary2View; 511 ViewHolder(View itemView)512 ViewHolder(View itemView) { 513 super(itemView); 514 iconView = (ImageView) itemView.findViewById(android.R.id.icon); 515 tileTitleView = (TextView) itemView.findViewById(R.id.tile_title); 516 tileSummaryView = (TextView) itemView.findViewById(R.id.tile_summary); 517 text1View = (TextView) itemView.findViewById(android.R.id.text1); 518 text2View = (TextView) itemView.findViewById(android.R.id.text2); 519 summary1View = (TextView) itemView.findViewById(R.id.summary1); 520 summary2View = (TextView) itemView.findViewById(R.id.summary2); 521 } 522 } 523 524 /** 525 * Data for a single support item. 526 */ 527 private static class SupportData { 528 529 final Intent intent; 530 final int metricsEvent; 531 @LayoutRes 532 final int type; 533 @DrawableRes 534 final int icon; 535 @StringRes 536 final int tileTitle; 537 final CharSequence tileTitleDescription; 538 final CharSequence tileSummary; 539 540 SupportData(Builder builder)541 private SupportData(Builder builder) { 542 this.type = builder.mType; 543 this.icon = builder.mIcon; 544 this.tileTitle = builder.mTileTitle; 545 this.tileTitleDescription = builder.mTileTitleDescription; 546 this.tileSummary = builder.mTileSummary; 547 this.intent = builder.mIntent; 548 this.metricsEvent = builder.mMetricsEvent; 549 } 550 551 static class Builder { 552 553 protected final Context mContext; 554 @LayoutRes 555 private final int mType; 556 @DrawableRes 557 private int mIcon; 558 @StringRes 559 private int mTileTitle; 560 private CharSequence mTileTitleDescription; 561 private CharSequence mTileSummary; 562 private Intent mIntent; 563 private int mMetricsEvent = -1; 564 Builder(Context context, @LayoutRes int type)565 Builder(Context context, @LayoutRes int type) { 566 mContext = context; 567 mType = type; 568 } 569 setIcon(@rawableRes int icon)570 Builder setIcon(@DrawableRes int icon) { 571 mIcon = icon; 572 return this; 573 } 574 setTileTitle(@tringRes int title)575 Builder setTileTitle(@StringRes int title) { 576 mTileTitle = title; 577 return this; 578 } 579 setTileTitleDescription(@tringRes int titleDescription)580 Builder setTileTitleDescription(@StringRes int titleDescription) { 581 mTileTitleDescription = mContext.getString(titleDescription); 582 return this; 583 } 584 setTileSummary(@tringRes int summary)585 Builder setTileSummary(@StringRes int summary) { 586 mTileSummary = mContext.getString(summary); 587 return this; 588 } 589 setTileSummary(CharSequence summary)590 Builder setTileSummary(CharSequence summary) { 591 mTileSummary = summary; 592 return this; 593 } 594 setMetricsEvent(int metricsEvent)595 Builder setMetricsEvent(int metricsEvent) { 596 mMetricsEvent = metricsEvent; 597 return this; 598 } 599 setIntent(Intent intent)600 Builder setIntent(Intent intent) { 601 mIntent = intent; 602 return this; 603 } 604 build()605 SupportData build() { 606 return new SupportData(this); 607 } 608 } 609 } 610 611 /** 612 * Data model for escalation cards. 613 */ 614 private static class EscalationData extends SupportData { 615 616 @StringRes 617 final int text1; 618 final CharSequence text2; 619 final boolean enabled1; 620 final boolean enabled2; 621 final CharSequence summary1; 622 final CharSequence summary2; 623 EscalationData(Builder builder)624 private EscalationData(Builder builder) { 625 super(builder); 626 this.text1 = builder.mText1; 627 this.text2 = builder.mText2; 628 this.summary1 = builder.mSummary1; 629 this.summary2 = builder.mSummary2; 630 this.enabled1 = builder.mEnabled1; 631 this.enabled2 = builder.mEnabled2; 632 } 633 634 static class Builder extends SupportData.Builder { 635 636 @StringRes 637 private int mText1; 638 private CharSequence mText2; 639 private CharSequence mSummary1; 640 private CharSequence mSummary2; 641 private boolean mEnabled1; 642 private boolean mEnabled2; 643 Builder(Context context, @LayoutRes int type)644 protected Builder(Context context, @LayoutRes int type) { 645 super(context, type); 646 } 647 Builder(Context context)648 Builder(Context context) { 649 this(context, TYPE_ESCALATION_OPTIONS); 650 } 651 setEnabled1(boolean enabled)652 Builder setEnabled1(boolean enabled) { 653 mEnabled1 = enabled; 654 return this; 655 } 656 setText1(@tringRes int text1)657 Builder setText1(@StringRes int text1) { 658 mText1 = text1; 659 return this; 660 } 661 setText2(@tringRes int text2)662 Builder setText2(@StringRes int text2) { 663 mText2 = mContext.getString(text2); 664 return this; 665 } 666 setText2(CharSequence text2)667 Builder setText2(CharSequence text2) { 668 mText2 = text2; 669 return this; 670 } 671 setSummary1(String summary1)672 Builder setSummary1(String summary1) { 673 mSummary1 = summary1; 674 return this; 675 } 676 setEnabled2(boolean enabled)677 Builder setEnabled2(boolean enabled) { 678 mEnabled2 = enabled; 679 return this; 680 } 681 setSummary2(String summary2)682 Builder setSummary2(String summary2) { 683 mSummary2 = summary2; 684 return this; 685 } 686 build()687 EscalationData build() { 688 return new EscalationData(this); 689 } 690 } 691 } 692 693 /** 694 * Support data for offline mode. 695 */ 696 private static final class OfflineEscalationData extends EscalationData { 697 698 final List<String> countries; 699 final SupportPhone tollFreePhone; 700 final SupportPhone tolledPhone; 701 OfflineEscalationData(Builder builder)702 private OfflineEscalationData(Builder builder) { 703 super(builder); 704 countries = builder.mCountries; 705 tollFreePhone = builder.mTollFreePhone; 706 tolledPhone = builder.mTolledPhone; 707 } 708 709 static final class Builder extends EscalationData.Builder { 710 711 private List<String> mCountries; 712 private SupportPhone mTollFreePhone; 713 private SupportPhone mTolledPhone; 714 Builder(Context context)715 Builder(Context context) { 716 super(context, TYPE_ESCALATION_OPTIONS_OFFLINE); 717 } 718 setCountries(List<String> countries)719 Builder setCountries(List<String> countries) { 720 mCountries = countries; 721 return this; 722 } 723 setTollFreePhone(SupportPhone phone)724 Builder setTollFreePhone(SupportPhone phone) { 725 mTollFreePhone = phone; 726 return this; 727 } 728 setTolledPhone(SupportPhone phone)729 Builder setTolledPhone(SupportPhone phone) { 730 mTolledPhone = phone; 731 return this; 732 } 733 build()734 OfflineEscalationData build() { 735 return new OfflineEscalationData(this); 736 } 737 } 738 } 739 } 740