11a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler/*
21a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Copyright (C) 2010 The Android Open Source Project
31a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler *
41a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Licensed under the Apache License, Version 2.0 (the "License");
51a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * you may not use this file except in compliance with the License.
61a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * You may obtain a copy of the License at
71a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler *
81a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler *      http://www.apache.org/licenses/LICENSE-2.0
91a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler *
101a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Unless required by applicable law or agreed to in writing, software
111a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * distributed under the License is distributed on an "AS IS" BASIS,
121a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * See the License for the specific language governing permissions and
141a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * limitations under the License.
151a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler */
161a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
171a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadlerpackage com.android.email.activity.setup;
181a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
191a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadlerimport android.app.Activity;
201a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadlerimport android.app.Fragment;
211a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadlerimport android.content.Context;
228d22e85e459df3d94968389852859dacaf2baafeAndy Stadlerimport android.os.AsyncTask;
231a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadlerimport android.os.Bundle;
243432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport android.view.KeyEvent;
25112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadlerimport android.view.View;
26112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadlerimport android.view.View.OnClickListener;
27206109cf44e27e90e4a5208daa289704aa451198Todd Kennedyimport android.view.View.OnFocusChangeListener;
283432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport android.view.inputmethod.EditorInfo;
29206109cf44e27e90e4a5208daa289704aa451198Todd Kennedyimport android.view.inputmethod.InputMethodManager;
30112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadlerimport android.widget.Button;
31206109cf44e27e90e4a5208daa289704aa451198Todd Kennedyimport android.widget.TextView;
323432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport android.widget.TextView.OnEditorActionListener;
333432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo
343432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport com.android.email.R;
353432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport com.android.email.activity.UiUtilities;
363432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport com.android.emailcommon.provider.Account;
373432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komaloimport com.android.emailcommon.provider.HostAuth;
381a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
391a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler/**
401a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Common base class for server settings fragments, so they can be more easily manipulated by
411a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * AccountSettingsXL.  Provides the following common functionality:
421a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler *
431a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Activity-provided callbacks
441a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Activity callback during onAttach
451a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler * Present "Next" button and respond to its clicks
461a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler */
47fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadlerpublic abstract class AccountServerBaseFragment extends Fragment
48112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        implements AccountCheckSettingsFragment.Callbacks, OnClickListener {
49112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler
50ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo    private static final String BUNDLE_KEY_SETTINGS = "AccountServerBaseFragment.settings";
51ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo    private static final String BUNDLE_KEY_ACTIVITY_TITLE = "AccountServerBaseFragment.title";
521a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
5326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    protected Activity mContext;
541a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    protected Callback mCallback = EmptyCallback.INSTANCE;
55206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    /**
56206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     * Whether or not we are in "settings mode". We re-use the same screens for both the initial
57206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     * account creation as well as subsequent account modification. If <code>mSettingsMode</code>
58206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     * if <code>false</code>, we are in account creation mode. Otherwise, we are in account
59206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     * modification mode.
60206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     */
61112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler    protected boolean mSettingsMode;
62fe68c0e7c2672e09076038b36ad24f095633d313Todd Kennedy    /*package*/ HostAuth mLoadedSendAuth;
63fe68c0e7c2672e09076038b36ad24f095633d313Todd Kennedy    /*package*/ HostAuth mLoadedRecvAuth;
64c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy
6526cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    protected SetupData mSetupData;
6626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler
67112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler    // This is null in the setup wizard screens, and non-null in AccountSettings mode
682fbb3db5d86210d03175ce77ff08c989a96c5864Makoto Onuki    private Button mProceedButton;
698d22e85e459df3d94968389852859dacaf2baafeAndy Stadler    // This is used to debounce multiple clicks on the proceed button (which does async work)
7064c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy    private boolean mProceedButtonPressed;
71040ddf60cfef4aaecf4bfe1f897fce3248d777a4Todd Kennedy    /*package*/ String mBaseScheme = "protocol";
721a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
731a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
741a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     * Callback interface that owning activities must provide
751a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
761a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    public interface Callback {
771a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        /**
781a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler         * Called each time the user-entered input transitions between valid and invalid
791a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler         * @param enable true to enable proceed/next button, false to disable
801a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler         */
811a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        public void onEnableProceedButtons(boolean enable);
82fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler
831a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        /**
84fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler         * Called when user clicks "next".  Starts account checker.
851a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler         * @param checkMode values from {@link SetupData}
86fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler         * @param target the fragment that requested the check
871a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler         */
88fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        public void onProceedNext(int checkMode, AccountServerBaseFragment target);
89fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler
90fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        /**
912731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * Called when account checker completes.  Fragments are responsible for saving
92fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler         * own edited data;  This is primarily for the activity to do post-check navigation.
932731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * @param result check settings result code - success is CHECK_SETTINGS_OK
9426cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler         * @param setupData possibly modified SetupData
95fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler         */
9626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        public void onCheckSettingsComplete(int result, SetupData setupData);
971a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
981a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
991a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    private static class EmptyCallback implements Callback {
1001a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        public static final Callback INSTANCE = new EmptyCallback();
1011a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        @Override public void onEnableProceedButtons(boolean enable) { }
102fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        @Override public void onProceedNext(int checkMode, AccountServerBaseFragment target) { }
10326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        @Override public void onCheckSettingsComplete(int result, SetupData setupData) { }
1041a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
1051a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
1061a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
10726cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler     * Creates and returns a bundle of arguments in the format we expect
10826cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler     *
10926cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler     * @param settingsMode True if we're in settings, false if we're in account creation
11026cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler     * @return Arg bundle
1111a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
11226cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    public static Bundle getArgs(Boolean settingsMode) {
11326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final Bundle setupModeArgs = new Bundle(1);
11426cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        setupModeArgs.putBoolean(BUNDLE_KEY_SETTINGS, settingsMode);
11526cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        return setupModeArgs;
1161a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
1171a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
11826cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    public AccountServerBaseFragment() {}
119c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy
1201a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
121112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler     * At onCreate time, read the fragment arguments
1221a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
1231a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    @Override
1241a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    public void onCreate(Bundle savedInstanceState) {
1251a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        super.onCreate(savedInstanceState);
1261a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
127112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        // Get arguments, which modally switch us into "settings" mode (different appearance)
128112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        mSettingsMode = false;
12926cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        if (savedInstanceState != null) {
13026cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler            mSettingsMode = savedInstanceState.getBoolean(BUNDLE_KEY_SETTINGS);
13126cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        } else if (getArguments() != null) {
132112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler            mSettingsMode = getArguments().getBoolean(BUNDLE_KEY_SETTINGS);
133112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        }
134f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        setHasOptionsMenu(true);
1351a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
1361a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
137112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler    /**
138112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler     * Called from onCreateView, to do settings mode configuration
139112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler     */
140112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler    protected void onCreateViewSettingsMode(View view) {
141112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        if (mSettingsMode) {
1422fbb3db5d86210d03175ce77ff08c989a96c5864Makoto Onuki            UiUtilities.getView(view, R.id.cancel).setOnClickListener(this);
143219c3b5b8474bc0b95a9dcab21067ff603fccb15Tony Mantler            mProceedButton = UiUtilities.getView(view, R.id.done);
144112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler            mProceedButton.setOnClickListener(this);
145112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler            mProceedButton.setEnabled(false);
146e6c6587b04a589eeb04006f75759c09ea10811e0Andy Stadler        }
1471a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
1481a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
1491a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    @Override
150ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo    public void onActivityCreated(Bundle savedInstanceState) {
151ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo        // startPreferencePanel launches this fragment with the right title initially, but
152ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo        // if the device is rotate we must set the title ourselves
15326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        mContext = getActivity();
154ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo        if (mSettingsMode && savedInstanceState != null) {
15526cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler            mContext.setTitle(savedInstanceState.getString(BUNDLE_KEY_ACTIVITY_TITLE));
156ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo        }
15726cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        SetupData.SetupDataContainer container = (SetupData.SetupDataContainer) mContext;
15826cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        mSetupData = container.getSetupData();
15926cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler
160ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo        super.onActivityCreated(savedInstanceState);
161ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo    }
162ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo
163ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo    @Override
164ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo    public void onSaveInstanceState(Bundle outState) {
165ae594dc0ca4748a97ee8ae05c5f5c828121934e8Jorge Lugo        outState.putString(BUNDLE_KEY_ACTIVITY_TITLE, (String) getActivity().getTitle());
16626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        outState.putBoolean(BUNDLE_KEY_SETTINGS, mSettingsMode);
1671a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
1681a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
169206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    @Override
1706fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo    public void onDetach() {
1716fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo        super.onDetach();
1726fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo
1736fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo        // Ensure that we don't have any callbacks at this point.
1746fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo        mCallback = EmptyCallback.INSTANCE;
1756fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo    }
1766fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo
1776fc2585327025d4e1ef7a488a7a075284c71773dBen Komalo    @Override
178206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    public void onPause() {
179206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy        // Hide the soft keyboard if we lose focus
18026cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final InputMethodManager imm =
181206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
182206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy        imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
183206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy        super.onPause();
184206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    }
185206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy
1861a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
187112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler     * Implements OnClickListener
1881a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
1891a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    @Override
190112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler    public void onClick(View v) {
191112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        switch (v.getId()) {
192112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler            case R.id.cancel:
193112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler                getActivity().onBackPressed();
194112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler                break;
195112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler            case R.id.done:
1968d22e85e459df3d94968389852859dacaf2baafeAndy Stadler                // Simple debounce - just ignore while checks are underway
1978d22e85e459df3d94968389852859dacaf2baafeAndy Stadler                if (mProceedButtonPressed) {
1988d22e85e459df3d94968389852859dacaf2baafeAndy Stadler                    return;
1998d22e85e459df3d94968389852859dacaf2baafeAndy Stadler                }
2008d22e85e459df3d94968389852859dacaf2baafeAndy Stadler                mProceedButtonPressed = true;
2011a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler                onNext();
202112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler                break;
2031a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        }
2041a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
2051a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
2061a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
2071a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     * Activity provides callbacks here.
2081a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
2091a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    public void setCallback(Callback callback) {
2101a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
2111a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        mContext = getActivity();
2121a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
2131a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
2141a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
2151a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     * Enable/disable the "next" button
2161a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
2171a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    public void enableNextButton(boolean enable) {
218112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        // If we are in settings "mode" we may be showing our own next button, and we'll
219112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        // enable it directly, here
220112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        if (mProceedButton != null) {
221112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler            mProceedButton.setEnabled(enable);
2221a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        }
22364c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy        clearButtonBounce();
2241a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
225112ed496f817ebeab6b1ee1d5117259ef80342b2Andy Stadler        // TODO: This supports the phone UX activities and will be removed
2261a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler        mCallback.onEnableProceedButtons(enable);
2271a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    }
2281a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
2291a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
230206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     * Make the given text view uneditable. If the text view is ever focused, the specified
231206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     * error message will be displayed.
232206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy     */
233206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    protected void makeTextViewUneditable(final TextView view, final String errorMessage) {
234206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy        // We're editing an existing account; don't allow modification of the user name
235206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy        if (mSettingsMode) {
236206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy            view.setKeyListener(null);
237206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy            view.setFocusable(true);
238206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy            view.setOnFocusChangeListener(new OnFocusChangeListener() {
239206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                @Override
240206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                public void onFocusChange(View v, boolean hasFocus) {
241206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                    if (hasFocus) {
242206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        // Framework will not auto-hide IME; do it ourselves
243206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        InputMethodManager imm = (InputMethodManager)mContext.
244206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                                getSystemService(Context.INPUT_METHOD_SERVICE);
245206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
246206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        view.setError(errorMessage);
247206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                    } else {
248206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        view.setError(null);
249206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                    }
250206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                }
251206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy            });
252206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy            view.setOnClickListener(new OnClickListener() {
253206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                @Override
254206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                public void onClick(View v) {
255206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                    if (view.getError() == null) {
256206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        view.setError(errorMessage);
257206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                    } else {
258206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                        view.setError(null);
259206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                    }
260206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy                }
261206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy            });
262206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy        }
263206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    }
264206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy
265206109cf44e27e90e4a5208daa289704aa451198Todd Kennedy    /**
2663432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo     * A keyboard listener which dismisses the keyboard when "DONE" is pressed, but doesn't muck
2673432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo     * around with focus. This is useful in settings screens, as we don't want focus to change
2683432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo     * since some fields throw up errors when they're focused to give the user more info.
2693432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo     */
2703432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo    protected final OnEditorActionListener mDismissImeOnDoneListener =
2713432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo            new OnEditorActionListener() {
2723432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo        @Override
2733432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
2743432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo            if (actionId == EditorInfo.IME_ACTION_DONE) {
2753432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                // Dismiss soft keyboard but don't modify focus.
2763432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                final Context context = getActivity();
2773432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                if (context == null) {
2783432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                    return false;
2793432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                }
28026cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                final InputMethodManager imm = (InputMethodManager) context.getSystemService(
2813432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                        Context.INPUT_METHOD_SERVICE);
2823432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                if (imm != null && imm.isActive()) {
2833432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                    imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
2843432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                }
2853432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo                return true;
2863432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo            }
2873432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo            return false;
2883432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo        }
2893432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo    };
2903432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo
2913432bdb757c4195fb4726c8b401f2261e78d75a7Ben Komalo    /**
29264c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy     * Clears the "next" button de-bounce flags and allows the "next" button to activate.
29364c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy     */
294463584d23f747cfbbd9856b39390269342363b41Tony Mantler    protected void clearButtonBounce() {
29564c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy        mProceedButtonPressed = false;
29664c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy    }
29764c7a437ac94bc0a1025804507b59d453caecd2bTodd Kennedy
2988d22e85e459df3d94968389852859dacaf2baafeAndy Stadler    /**
299fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     * Implements AccountCheckSettingsFragment.Callbacks
300fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     *
3016e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler     * Handle OK or error result from check settings.  Save settings (async), and then
3026e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler     * exit to previous fragment.
30355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
304fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    @Override
30526cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    public void onCheckSettingsComplete(final int settingsResult, SetupData setupData) {
30626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        mSetupData = setupData;
3076e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler        new AsyncTask<Void, Void, Void>() {
3086e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler            @Override
3096e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler            protected Void doInBackground(Void... params) {
3106e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                if (settingsResult == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) {
31126cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                    if (mSetupData.getFlowMode() == SetupData.FLOW_MODE_EDIT) {
3126e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                        saveSettingsAfterEdit();
3136e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                    } else {
3146e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                        saveSettingsAfterSetup();
3156e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                    }
3166e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                }
3176e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                return null;
3182731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            }
3196e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler
3206e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler            @Override
3216e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler            protected void onPostExecute(Void result) {
3226e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler                // Signal to owning activity that a settings check completed
32326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                mCallback.onCheckSettingsComplete(settingsResult, mSetupData);
3246e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler            }
325bc2eaadde987044027b57d241e635de014bdb8baMakoto Onuki        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
3262731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    }
3272731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
3282731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /**
3292731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * Implements AccountCheckSettingsFragment.Callbacks
3302731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * This is overridden only by AccountSetupExchange
3312731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     */
3322731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    @Override
33326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    public void onAutoDiscoverComplete(int result, SetupData setupData) {
3342731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        throw new IllegalStateException();
33555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
33655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
33755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
338c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy     * Returns whether or not any settings have changed.
339c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy     */
340c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy    public boolean haveSettingsChanged() {
34126cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final Account account = mSetupData.getAccount();
342c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy
34326cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final HostAuth sendAuth = account.getOrCreateHostAuthSend(mContext);
34426cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final boolean sendChanged = (mLoadedSendAuth != null && !mLoadedSendAuth.equals(sendAuth));
345fe68c0e7c2672e09076038b36ad24f095633d313Todd Kennedy
34626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mContext);
34726cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        final boolean recvChanged = (mLoadedRecvAuth != null && !mLoadedRecvAuth.equals(recvAuth));
348c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy
349fe68c0e7c2672e09076038b36ad24f095633d313Todd Kennedy        return sendChanged || recvChanged;
350c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy    }
351c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy
352c890a4e4a2cbb489aea4847cf25368a723586530Todd Kennedy    /**
3531a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     * Save settings after "OK" result from checker.  Concrete classes must implement.
3546e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler     * This is called from a worker thread and is allowed to perform DB operations.
3551a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
3561a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    public abstract void saveSettingsAfterEdit();
3571a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler
3581a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    /**
359fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     * Save settings after "OK" result from checker.  Concrete classes must implement.
3606e71978ec38add2edf3ac5f3dd1f9abeea9c1ab6Andy Stadler     * This is called from a worker thread and is allowed to perform DB operations.
361fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     */
362fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    public abstract void saveSettingsAfterSetup();
363fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler
364fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    /**
3651a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     * Respond to a click of the "Next" button.  Concrete classes must implement.
3661a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler     */
3671a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler    public abstract void onNext();
3681a5e1e159352f6e21bde878eebca3e3a1896045cAndrew Stadler}
369