1 /*
2  * Copyright (C) 2017 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 
17 package com.android.tv.tuner.setup;
18 
19 import android.os.Bundle;
20 import android.support.annotation.NonNull;
21 import androidx.leanback.widget.GuidanceStylist.Guidance;
22 import androidx.leanback.widget.GuidedAction;
23 import androidx.leanback.widget.GuidedActionsStylist;
24 import android.text.InputFilter;
25 import android.text.InputFilter.AllCaps;
26 import android.view.View;
27 import android.widget.TextView;
28 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
29 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
30 import com.android.tv.common.util.LocationUtils;
31 import com.android.tv.common.util.PostalCodeUtils;
32 import com.android.tv.tuner.R;
33 import java.util.List;
34 
35 /** A fragment for users to enter postal code. */
36 public class PostalCodeFragment extends SetupMultiPaneFragment {
37     public static final String ACTION_CATEGORY = "com.android.tv.tuner.setup.PostalCodeFragment";
38     public static final String KEY_POSTAL_CODE = "postal_code";
39     public static final String KEY_GET_LOCATION_FAILED = "get_location_failed";
40     private static final int VIEW_TYPE_EDITABLE = 1;
41 
42     @Override
onCreateContentFragment()43     protected SetupGuidedStepFragment onCreateContentFragment() {
44         ContentFragment fragment = new ContentFragment();
45         Bundle arguments = new Bundle();
46         arguments.putBoolean(SetupGuidedStepFragment.KEY_THREE_PANE, true);
47         if (getArguments() != null) {
48             arguments.putBoolean(
49                     KEY_GET_LOCATION_FAILED,
50                     getArguments().getBoolean(KEY_GET_LOCATION_FAILED, false));
51         }
52         fragment.setArguments(arguments);
53         return fragment;
54     }
55 
56     @Override
getActionCategory()57     protected String getActionCategory() {
58         return ACTION_CATEGORY;
59     }
60 
61     @Override
needsDoneButton()62     protected boolean needsDoneButton() {
63         return true;
64     }
65 
66     @Override
needsSkipButton()67     protected boolean needsSkipButton() {
68         return true;
69     }
70 
71     @Override
setOnClickAction(View view, final String category, final int actionId)72     protected void setOnClickAction(View view, final String category, final int actionId) {
73         if (actionId == ACTION_DONE) {
74             view.setOnClickListener(
75                     new View.OnClickListener() {
76                         @Override
77                         public void onClick(View view) {
78                             CharSequence postalCode =
79                                     ((ContentFragment) getContentFragment())
80                                             .mEditedActionTitleView.getText();
81                             String region = LocationUtils.getCurrentCountry(getContext());
82                             if (postalCode != null && PostalCodeUtils.matches(postalCode, region)) {
83                                 String postalCodeString = postalCode.toString();
84                                 PostalCodeUtils.setLastPostalCode(getContext(), postalCodeString);
85                                 Bundle params = new Bundle();
86                                 params.putString(KEY_POSTAL_CODE, postalCodeString);
87                                 onActionClick(category, actionId, params);
88                             } else {
89                                 ContentFragment contentFragment =
90                                         (ContentFragment) getContentFragment();
91                                 contentFragment.mEditAction.setDescription(
92                                         getString(R.string.postal_code_invalid_warning));
93                                 contentFragment.notifyActionChanged(0);
94                                 contentFragment.mEditedActionView.performClick();
95                             }
96                         }
97                     });
98         } else if (actionId == ACTION_SKIP) {
99             super.setOnClickAction(view, category, ACTION_SKIP);
100         }
101     }
102 
103     /** The content fragment of {@link PostalCodeFragment}. */
104     public static class ContentFragment extends SetupGuidedStepFragment {
105         private GuidedAction mEditAction;
106         private View mEditedActionView;
107         private TextView mEditedActionTitleView;
108         private View mDoneActionView;
109         private boolean mProceed;
110 
111         @Override
onGuidedActionFocused(GuidedAction action)112         public void onGuidedActionFocused(GuidedAction action) {
113             if (action.equals(mEditAction)) {
114                 if (mProceed) {
115                     // "NEXT" in IME was just clicked, moves focus to Done button.
116                     if (mDoneActionView == null) {
117                         mDoneActionView = getDoneButton();
118                     }
119                     mDoneActionView.requestFocus();
120                     mProceed = false;
121                 } else {
122                     // Directly opens IME to input postal/zip code.
123                     if (mEditedActionView == null) {
124                         int maxLength = PostalCodeUtils.getRegionMaxLength(getContext());
125                         mEditedActionView = getView().findViewById(R.id.guidedactions_editable);
126                         mEditedActionTitleView =
127                                 mEditedActionView.findViewById(R.id.guidedactions_item_title);
128                         mEditedActionTitleView.setFilters(
129                                 new InputFilter[] {
130                                     new InputFilter.LengthFilter(maxLength), new AllCaps()
131                                 });
132                     }
133                     mEditedActionView.performClick();
134                 }
135             }
136         }
137 
138         @Override
onGuidedActionEditedAndProceed(GuidedAction action)139         public long onGuidedActionEditedAndProceed(GuidedAction action) {
140             mProceed = true;
141             return 0;
142         }
143 
144         @NonNull
145         @Override
onCreateGuidance(Bundle savedInstanceState)146         public Guidance onCreateGuidance(Bundle savedInstanceState) {
147             String title = getString(R.string.postal_code_guidance_title);
148             StringBuilder description = new StringBuilder();
149             if (getArguments().getBoolean(KEY_GET_LOCATION_FAILED, false)) {
150                 description
151                         .append(getString(R.string
152                                 .postal_code_guidance_description_get_location_failed))
153                         .append(" ");
154             }
155             description.append(getString(R.string.postal_code_guidance_description));
156             String breadcrumb = getString(R.string.ut_setup_breadcrumb);
157             return new Guidance(title, description.toString(), breadcrumb, null);
158         }
159 
160         @Override
onCreateActions( @onNull List<GuidedAction> actions, Bundle savedInstanceState)161         public void onCreateActions(
162                 @NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
163             String description = getString(R.string.postal_code_action_description);
164             mEditAction =
165                     new GuidedAction.Builder(getActivity())
166                             .id(0)
167                             .editable(true)
168                             .description(description)
169                             .build();
170             actions.add(mEditAction);
171         }
172 
173         @Override
getActionCategory()174         protected String getActionCategory() {
175             return ACTION_CATEGORY;
176         }
177 
178         @Override
onCreateActionsStylist()179         public GuidedActionsStylist onCreateActionsStylist() {
180             return new GuidedActionsStylist() {
181                 @Override
182                 public int getItemViewType(GuidedAction action) {
183                     if (action.isEditable()) {
184                         return VIEW_TYPE_EDITABLE;
185                     }
186                     return super.getItemViewType(action);
187                 }
188 
189                 @Override
190                 public int onProvideItemLayoutId(int viewType) {
191                     if (viewType == VIEW_TYPE_EDITABLE) {
192                         return R.layout.guided_action_editable;
193                     }
194                     return super.onProvideItemLayoutId(viewType);
195                 }
196             };
197         }
198     }
199 }
200