Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9fcb2c9 authored by Fan Zhang's avatar Fan Zhang Committed by Android (Google) Code Review
Browse files

Merge "When offline show a list of countries with phone support." into nyc-mr1-dev

parents 17eb2e2e a44b1efb
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2016 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/card_background_grey"
    android:gravity="center_horizontal"
    android:paddingBottom="40dp"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/support_country_list_title"
            android:textAppearance="@style/TextAppearance.Small"
            android:textColor="?android:attr/textColorSecondary"/>
        <Spinner
            android:id="@+id/spinner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <Button
        android:id="@android:id/text1"
        style="@style/SupportPrimaryButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"/>
    <Button
        android:id="@android:id/text2"
        style="@style/SupportSecondaryButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:minHeight="48dp"/>
</LinearLayout>
+12 −0
Original line number Diff line number Diff line
@@ -7522,12 +7522,24 @@
        <xliff:g id="start_day">%s</xliff:g> - <xliff:g id="end_day">%s</xliff:g>, <xliff:g id="start_time">%s</xliff:g> - <xliff:g id="end_time">%s</xliff:g>&lt;br&gt;
    </string>
    <!-- Button label for choosing country for phone support. [CHAR LIMIT=40]-->
    <string name="support_country_list_title">Support for:</string>
    <!-- Template for formatting country and language. eg Canada - French [CHAR LIMIT=NONE]-->
    <string name="support_country_format"><xliff:g id="country" example="Canada">%s</xliff:g> - <xliff:g id="language" example="French">%s</xliff:g></string>
    <!-- Title text that indicates there is not internet connection. [CHAR LIMIT=80]-->
    <string name="support_offline_title">You\'re offline</string>
    <!-- Summary text telling user to connect to Internet in order to request customer support. [CHAR LIMIT=NONE]-->
    <string name="support_offline_summary">To reach support, first connect to Wi-Fi or data.</string>
    <!-- Title text for a list of international support phone numbers. [CHAR LIMIT=60]-->
    <string name="support_international_phone_title">Traveling aboard?</string>
    <!-- Description text warning international phone charge may apply when dialing support numbers. [CHAR LIMIT=NONE]-->
    <string name="support_international_phone_summary">International charges may apply</string>
    <!-- Button label for contacting customer support by phone [CHAR LIMIT=20]-->
    <string name="support_escalation_by_phone">Phone</string>
+155 −25
Original line number Diff line number Diff line
@@ -28,7 +28,10 @@ import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;

import com.android.internal.logging.MetricsLogger;
@@ -36,6 +39,7 @@ import com.android.internal.logging.MetricsProto;
import com.android.settings.R;
import com.android.settings.overlay.SupportFeatureProvider;
import com.android.settings.support.SupportDisclaimerDialogFragment;
import com.android.settings.support.SupportPhone;

import java.util.ArrayList;
import java.util.List;
@@ -51,15 +55,19 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd

    private static final int TYPE_TITLE = R.layout.support_item_title;
    private static final int TYPE_ESCALATION_OPTIONS = R.layout.support_escalation_options;
    private static final int TYPE_ESCALATION_OPTIONS_OFFLINE =
            R.layout.support_offline_escalation_options;
    private static final int TYPE_SUPPORT_TILE = R.layout.support_tile;
    private static final int TYPE_SIGN_IN_BUTTON = R.layout.support_sign_in_button;

    private final Activity mActivity;
    private final EscalationClickListener mEscalationClickListener;
    private final SpinnerItemSelectListener mSpinnerItemSelectListener;
    private final SupportFeatureProvider mSupportFeatureProvider;
    private final View.OnClickListener mItemClickListener;
    private final List<SupportData> mSupportData;

    private String mSelectedCountry;
    private boolean mHasInternet;
    private Account mAccount;

@@ -69,6 +77,7 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
        mSupportFeatureProvider = supportFeatureProvider;
        mItemClickListener = itemClickListener;
        mEscalationClickListener = new EscalationClickListener();
        mSpinnerItemSelectListener = new SpinnerItemSelectListener();
        mSupportData = new ArrayList<>();
        // Optimistically assume we have Internet access. It will be updated later to correct value.
        mHasInternet = true;
@@ -92,6 +101,9 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
            case TYPE_ESCALATION_OPTIONS:
                bindEscalationOptions(holder, data);
                break;
            case TYPE_ESCALATION_OPTIONS_OFFLINE:
                bindOfflineEscalationOptions(holder, (OfflineSupportData) data);
                break;
            default:
                bindSupportTile(holder, data);
                break;
@@ -145,15 +157,16 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
        mSupportData.clear();
        if (mAccount == null) {
            addSignInPromo();
        } else {
        } else if (mHasInternet) {
            addEscalationCards();
        } else {
            addOfflineEscalationCards();
        }
        addMoreHelpItems();
        notifyDataSetChanged();
    }

    private void addEscalationCards() {
        if (mHasInternet) {
        if (mSupportFeatureProvider.isAlwaysOperating(PHONE)
                || mSupportFeatureProvider.isAlwaysOperating(CHAT)) {
            mSupportData.add(new SupportData.Builder(mActivity, TYPE_TITLE)
@@ -172,12 +185,6 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
                    .setText2(mSupportFeatureProvider.getOperationHours(mActivity, PHONE))
                    .build());
        }
        } else {
            mSupportData.add(new SupportData.Builder(mActivity, TYPE_TITLE)
                    .setText1(R.string.support_offline_title)
                    .setText2(R.string.support_offline_summary)
                    .build());
        }
        final SupportData.Builder builder =
                new SupportData.Builder(mActivity, TYPE_ESCALATION_OPTIONS);
        if (mSupportFeatureProvider.isSupportTypeEnabled(mActivity, PHONE)) {
@@ -193,6 +200,20 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
        mSupportData.add(builder.build());
    }

    private void addOfflineEscalationCards() {
        mSupportData.add(new SupportData.Builder(mActivity, TYPE_TITLE)
                .setText1(R.string.support_offline_title)
                .setText2(R.string.support_offline_summary)
                .build());
        final OfflineSupportData.Builder builder = new OfflineSupportData.Builder(mActivity);
        builder.setCountries(mSupportFeatureProvider.getPhoneSupportCountries())
                .setTollFreePhone(mSupportFeatureProvider.getSupportPhones(
                        mSelectedCountry, true /* isTollFree */))
                .setTolledPhone(mSupportFeatureProvider.getSupportPhones(
                        mSelectedCountry, false /* isTollFree */));
        mSupportData.add(builder.build());
    }

    private void addSignInPromo() {
        mSupportData.add(new SupportData.Builder(mActivity, TYPE_TITLE)
                .setText1(R.string.support_sign_in_required_title)
@@ -246,6 +267,38 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
        }
    }

    private void bindOfflineEscalationOptions(ViewHolder holder, OfflineSupportData data) {
        // Bind spinner
        final Spinner spinner = (Spinner) holder.itemView.findViewById(R.id.spinner);
        final ArrayAdapter<String> adapter = new ArrayAdapter(
                mActivity, android.R.layout.simple_spinner_dropdown_item, data.countries);
        spinner.setAdapter(adapter);
        final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes();
        for (int i = 0; i < countryCodes.size(); i++) {
            if (TextUtils.equals(countryCodes.get(i), mSelectedCountry)) {
                spinner.setSelection(i);
                break;
            }
        }
        spinner.setOnItemSelectedListener(mSpinnerItemSelectListener);
        // Bind buttons
        if (data.tollFreePhone != null) {
            holder.text1View.setText(data.tollFreePhone.number);
            holder.text1View.setVisibility(View.VISIBLE);
            holder.text1View.setOnClickListener(mEscalationClickListener);
        } else {
            holder.text1View.setVisibility(View.GONE);
        }
        if (data.tolledPhone != null) {
            holder.text2View.setText(
                    mActivity.getString(R.string.support_international_phone_title));
            holder.text2View.setVisibility(View.VISIBLE);
            holder.text2View.setOnClickListener(mEscalationClickListener);
        } else {
            holder.text2View.setVisibility(View.GONE);
        }
    }

    private void bindSignInPromoTile(ViewHolder holder, SupportData data) {
        holder.text1View.setText(data.text1);
        holder.text2View.setText(data.text2);
@@ -299,7 +352,7 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
                                0 /* requestCode */);
                        break;
                }
            } else {
            } else if (mHasInternet) {
                switch (v.getId()) {
                    case android.R.id.text1:
                        MetricsLogger.action(mActivity,
@@ -312,7 +365,37 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
                        tryStartDisclaimerAndSupport(CHAT);
                        break;
                }
            } else {
                switch (v.getId()) {
                    case android.R.id.text1:
                        final SupportPhone phone = mSupportFeatureProvider
                                .getSupportPhones(mSelectedCountry, true /* isTollFree */);
                        if (phone != null) {
                            mActivity.startActivity(phone.getDialIntent());
                        }
                        break;
                    case android.R.id.text2:
                        break;
                }
            }
        }
    }

    private final class SpinnerItemSelectListener implements AdapterView.OnItemSelectedListener {

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes();
            final String selectedCountry = countryCodes.get(position);
            if (!TextUtils.equals(selectedCountry, mSelectedCountry)) {
                mSelectedCountry = selectedCountry;
                refreshData();
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            // Do nothing.
        }
    }

@@ -340,7 +423,7 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
    /**
     * Data for a single support item.
     */
    private static final class SupportData {
    private static class SupportData {

        final Intent intent;
        final int metricsEvent;
@@ -369,7 +452,7 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
            this.metricsEvent = builder.mMetricsEvent;
        }

        static final class Builder {
        static class Builder {

            private final Context mContext;
            @LayoutRes
@@ -446,4 +529,51 @@ public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAd
            }
        }
    }

    /**
     * Support data for offline mode.
     */
    private static final class OfflineSupportData extends SupportData {

        final List<String> countries;
        final SupportPhone tollFreePhone;
        final SupportPhone tolledPhone;

        private OfflineSupportData(Builder builder) {
            super(builder);
            countries = builder.mCountries;
            tollFreePhone = builder.mTollFreePhone;
            tolledPhone = builder.mTolledPhone;
        }

        static final class Builder extends SupportData.Builder {

            private List<String> mCountries;
            private SupportPhone mTollFreePhone;
            private SupportPhone mTolledPhone;

            Builder(Context context) {
                super(context, TYPE_ESCALATION_OPTIONS_OFFLINE);
            }

            Builder setCountries(List<String> countries) {
                mCountries = countries;
                return this;
            }

            Builder setTollFreePhone(SupportPhone phone) {
                mTollFreePhone = phone;
                return this;
            }

            Builder setTolledPhone(SupportPhone phone) {
                mTolledPhone = phone;
                return this;
            }

            OfflineSupportData build() {
                return new OfflineSupportData(this);
            }
        }
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -22,8 +22,11 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;

import com.android.settings.support.SupportPhone;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;

/**
 * Feature provider for support tab.
@@ -68,6 +71,22 @@ public interface SupportFeatureProvider {
     */
    String getEstimatedWaitTime(Context context, @SupportType int type);


    /**
     * Returns a list of country codes that have phone support.
     */
    List<String> getPhoneSupportCountryCodes();

    /**
     * Returns a list of countries that have phone support.
     */
    List<String> getPhoneSupportCountries();

    /**
     * Returns a support phone for specified country.
     */
    SupportPhone getSupportPhones(String countryCode, boolean isTollfree);

    /**
     * Whether or not a disclaimer dialog should be displayed.
     */
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.support;

import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;

import java.text.ParseException;

/**
 * Data model for a support phone number.
 */
public final class SupportPhone {

    public final String language;
    public final String number;
    public final boolean isTollFree;

    public SupportPhone(String config) throws ParseException {
        // Config follows this format: language:[tollfree|tolled]:number
        final String[] tokens = config.split(":");
        if (tokens.length != 3) {
            throw new ParseException("Phone config is invalid " + config, 0);
        }
        language = tokens[0];
        isTollFree = TextUtils.equals(tokens[1], "tollfree");
        number = tokens[2];
    }

    public Intent getDialIntent() {
        return new Intent(Intent.ACTION_DIAL)
                .setData(new Uri.Builder()
                        .scheme("tel")
                        .appendPath(number)
                        .build());
    }
}