1 /*
2  * Copyright (C) 2015 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.settings.name;
18 
19 import android.app.Activity;
20 import android.app.FragmentManager;
21 import android.os.Build;
22 import android.os.Bundle;
23 import android.text.TextUtils;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.ViewGroup;
27 
28 import androidx.annotation.NonNull;
29 import androidx.fragment.app.FragmentTransaction;
30 import androidx.leanback.app.GuidedStepSupportFragment;
31 import androidx.leanback.widget.GuidanceStylist;
32 import androidx.leanback.widget.GuidedAction;
33 import androidx.leanback.widget.GuidedActionsStylist;
34 
35 import com.android.tv.settings.R;
36 import com.android.tv.settings.name.setup.DeviceNameFlowStartActivity;
37 import com.android.tv.settings.util.AccessibilityHelper;
38 import com.android.tv.settings.util.GuidedActionsAlignUtil;
39 
40 import java.util.List;
41 
42 /**
43  * Fragment responsible for adding new device name.
44  */
45 public class DeviceNameSetCustomFragment extends GuidedStepSupportFragment {
46 
47     private GuidedAction mEditAction;
48 
newInstance()49     public static DeviceNameSetCustomFragment newInstance() {
50         return new DeviceNameSetCustomFragment();
51     }
52 
53     @Override
onCreateGuidanceStylist()54     public GuidanceStylist onCreateGuidanceStylist() {
55         return GuidedActionsAlignUtil.createGuidanceStylist();
56     }
57 
58     @Override
onCreateActionsStylist()59     public GuidedActionsStylist onCreateActionsStylist() {
60         return new GuidedActionsStylist() {
61             @Override
62             public int onProvideItemLayoutId() {
63                 return R.layout.guided_step_input_action;
64             }
65             @Override
66             protected void setupImeOptions(GuidedActionsStylist.ViewHolder vh,
67                     GuidedAction action) {
68                 // keep defaults
69             }
70         };
71     }
72 
73     @Override
74     public View onCreateView(LayoutInflater inflater, ViewGroup container,
75             Bundle savedInstanceState) {
76         View view = super.onCreateView(inflater, container, savedInstanceState);
77         return GuidedActionsAlignUtil.createView(view, this);
78     }
79 
80     @NonNull
81     @Override
82     public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
83         return new GuidanceStylist.Guidance(
84                 getString(R.string.select_device_name_title, Build.MODEL),
85                 getString(R.string.select_device_name_description),
86                 null,
87                 null);
88     }
89 
90     @Override
91     public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
92         mEditAction = new GuidedAction.Builder(getContext())
93                 .title("")
94                 .editable(true)
95                 .build();
96         actions.add(mEditAction);
97     }
98 
99     @Override
100     public void onResume() {
101         super.onResume();
102         openInEditMode(mEditAction);
103     }
104 
105     // Overriding this method removes the unpreferable enter transition animation of this fragment.
106     @Override
107     protected void onProvideFragmentTransitions() {
108         setEnterTransition(null);
109     }
110 
111     @Override
112     public long onGuidedActionEditedAndProceed(GuidedAction action) {
113         final CharSequence name = action.getTitle();
114         if (TextUtils.isGraphic(name)) {
115             DeviceManager.setDeviceName(getActivity(), name.toString());
116             getActivity().setResult(Activity.RESULT_OK);
117 
118             // Set the flag for the appropriate exit animation for setup.
119             if (getActivity() instanceof DeviceNameFlowStartActivity) {
120                 ((DeviceNameFlowStartActivity) getActivity()).setResultOk(true);
121             }
122             DeviceNameSuggestionStatus.getInstance(
123                     getActivity().getApplicationContext()).setFinished();
124             getActivity().finish();
125             return super.onGuidedActionEditedAndProceed(action);
126         } else {
127             popBackStackToGuidedStepSupportFragment(
128                     DeviceNameSetCustomFragment.class, FragmentManager.POP_BACK_STACK_INCLUSIVE);
129             return GuidedAction.ACTION_ID_CANCEL;
130         }
131     }
132 
133     @Override
134     protected void onAddSharedElementTransition(
135             FragmentTransaction ft, GuidedStepSupportFragment disappearing) {
136         // no-op
137     }
138 
139     @Override
140     public void onGuidedActionEditCanceled(GuidedAction action) {
141         // We need to ensure the IME is closed before navigating back. See b/233207859.
142         AccessibilityHelper.dismissKeyboard(getActivity(), getView());
143 
144         // We need to "pop to" current fragment with INCLUSIVE flag instead of popping to previous
145         // fragment because DeviceNameSetFragment was set to be root and not added on backstack.
146         popBackStackToGuidedStepSupportFragment(
147                 DeviceNameSetCustomFragment.class, FragmentManager.POP_BACK_STACK_INCLUSIVE);
148     }
149 }
150