Java tutorial
// 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.google.reviewit; import android.app.AlertDialog; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.LayoutRes; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.TextView; import com.google.common.base.Strings; import com.google.gerrit.extensions.api.GerritApi; import com.google.gerrit.extensions.restapi.RestApiException; import com.google.reviewit.app.ConfigManager; import com.google.reviewit.app.Preferences; import com.google.reviewit.app.QueryConfig; import com.google.reviewit.app.ServerConfig; import com.google.reviewit.util.FormatUtil; import com.google.reviewit.util.WidgetUtil; import com.urswolfer.gerrit.client.rest.GerritAuthData; import com.urswolfer.gerrit.client.rest.GerritRestApiFactory; import com.urswolfer.gerrit.client.rest.http.HttpStatusException; import java.net.MalformedURLException; import java.net.URL; import static com.google.reviewit.util.WidgetUtil.setGone; import static com.google.reviewit.util.WidgetUtil.setInvisible; import static com.google.reviewit.util.WidgetUtil.setVisible; public class ServerSettingsFragment extends BaseFragment { private static final String TAG = ServerSettingsFragment.class.getName(); private static final String ORIGIN = "com.google.reviewit.ServerSettingsFragment.ORIGIN"; private static final String SERVER_ID = "com.google.reviewit.ServerSettingsFragment.SERVER_ID"; public static ServerSettingsFragment create(Class<? extends Fragment> origin) { ServerSettingsFragment fragment = new ServerSettingsFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(ORIGIN, origin); fragment.setArguments(bundle); return fragment; } public static ServerSettingsFragment create(Class<? extends Fragment> origin, String serverId) { ServerSettingsFragment fragment = new ServerSettingsFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(ORIGIN, origin); bundle.putString(SERVER_ID, serverId); fragment.setArguments(bundle); return fragment; } @Override protected @LayoutRes int getLayout() { return R.layout.content_server_settings; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); init(); String serverId = getArguments() != null ? getArguments().getString(SERVER_ID) : null; displayServerConfig(serverId != null ? getApp().getConfigManager().getServerConfig(serverId) : null); } private void displayServerConfig(ServerConfig cfg) { if (cfg != null) { WidgetUtil.setText(v(R.id.idInput), cfg.id); WidgetUtil.setText(v(R.id.nameInput), cfg.name); WidgetUtil.setText(v(R.id.urlInput), cfg.url); WidgetUtil.setText(v(R.id.userInput), cfg.user); WidgetUtil.setText(v(R.id.passwordInput), cfg.password); displayCredentialsInfo(cfg.url); } else { WidgetUtil.setText(v(R.id.idInput), ""); WidgetUtil.setText(v(R.id.nameInput), ""); WidgetUtil.setText(v(R.id.urlInput), ""); WidgetUtil.setText(v(R.id.userInput), ""); WidgetUtil.setText(v(R.id.passwordInput), ""); displayCredentialsInfo(null); } } private void init() { final AutoCompleteTextView urlInput = (AutoCompleteTextView) v(R.id.urlInput); ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.urls)); urlInput.setAdapter(adapter); v(R.id.pasteCredentialsButton).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ClipboardManager clipboard = (ClipboardManager) getActivity() .getSystemService(Context.CLIPBOARD_SERVICE); if (clipboard.hasPrimaryClip() && clipboard.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); String pasteData = item.getText().toString(); if (!pasteData.contains("/.gitcookies")) { return; } pasteData = pasteData.substring(pasteData.indexOf("/.gitcookies")); pasteData = pasteData.substring(pasteData.lastIndexOf(",") + 1); int pos = pasteData.indexOf("="); String user = pasteData.substring(0, pos); pasteData = pasteData.substring(pos + 1); String password = pasteData.substring(0, pasteData.indexOf("\n")); WidgetUtil.setText(v(R.id.userInput), user); WidgetUtil.setText(v(R.id.passwordInput), password); // hide keyboard if it is open View view = getActivity().getCurrentFocus(); if (view != null) { ((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)) .hideSoftInputFromWindow(view.getWindowToken(), 0); } } } }); ((EditText) v(R.id.urlInput)).addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (Strings.isNullOrEmpty(textOf(R.id.nameInput))) { try { String host = new URL(s.toString()).getHost(); int pos = host.indexOf("."); WidgetUtil.setText(v(R.id.nameInput), pos > 0 ? host.substring(0, pos) : host); } catch (MalformedURLException e) { // ignore } } displayCredentialsInfo(s.toString()); } }); v(R.id.saveServerSettings).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { enabledForm(false); if (!isServerInputComplete()) { widgetUtil.showError(R.string.incompleteInput); enabledForm(true); return; } if (!isUrlValid()) { widgetUtil.showError(R.string.invalidUrl); enabledForm(true); return; } if (!hasUniqueName()) { widgetUtil.showError(getString(R.string.duplicate_server_name, textOf(R.id.nameInput))); enabledForm(true); return; } setVisible(v(R.id.statusTestConnection, R.id.statusTestConnectionProgress)); WidgetUtil.setText(v(R.id.statusTestConnectionText), null); new AsyncTask<Void, Void, String>() { private TextView status; private View statusTestConnectionProgress; private View statusTestConnection; @Override protected void onPreExecute() { super.onPreExecute(); status = tv(R.id.statusTestConnectionText); statusTestConnectionProgress = v(R.id.statusTestConnectionProgress); statusTestConnection = v(R.id.statusTestConnection); } @Override protected String doInBackground(Void... v) { return testConnection(); } protected void onPostExecute(String errorMsg) { if (errorMsg != null) { enabledForm(true); status.setTextColor(widgetUtil.color(R.color.statusFailed)); status.setText(getString(R.string.test_server_connection_failed)); setInvisible(statusTestConnectionProgress); new AlertDialog.Builder(getContext()).setTitle(getString(R.string.error_title)) .setMessage(getString(R.string.connection_failed, errorMsg)) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // do nothing } }).setNegativeButton(getString(R.string.save_anyway), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { setGone(statusTestConnection); onServerSave(saveServerSettings()); } }) .setIcon(android.R.drawable.ic_dialog_alert).show(); } else { status.setTextColor(widgetUtil.color(R.color.statusOk)); status.setText(getString(R.string.test_server_connection_ok)); setGone(statusTestConnection); onServerSave(saveServerSettings()); } } }.execute(); } }); enabledForm(true); setGone(v(R.id.statusTestConnection)); } private void enabledForm(boolean enable) { v(R.id.urlInput).setEnabled(enable); v(R.id.nameInput).setEnabled(enable); v(R.id.pasteCredentialsButton).setEnabled(enable); v(R.id.userInput).setEnabled(enable); v(R.id.passwordInput).setEnabled(enable); v(R.id.saveServerSettings).setEnabled(enable); } private boolean isServerInputComplete() { return !Strings.isNullOrEmpty(textOf(R.id.urlInput)) && !Strings.isNullOrEmpty(textOf(R.id.nameInput)) && !Strings.isNullOrEmpty(textOf(R.id.userInput)) && !Strings.isNullOrEmpty(textOf(R.id.passwordInput)); } private boolean isUrlValid() { try { new URL(textOf(R.id.urlInput)); return true; } catch (MalformedURLException e) { return false; } } private boolean hasUniqueName() { if (!Strings.isNullOrEmpty(textOf(R.id.idInput))) { // update of existing entry return true; } ServerConfig otherCfg = getApp().getConfigManager().getServerByName(textOf(R.id.nameInput)); return otherCfg == null; } private String testConnection() { GerritApi api = new GerritRestApiFactory().create(new GerritAuthData.Basic(textOf(R.id.urlInput), textOf(R.id.userInput), textOf(R.id.passwordInput))); try { api.changes().query().withLimit(1).get(); String version = api.config().server().getVersion(); Log.i(TAG, "version of " + textOf(R.id.nameInput) + ": " + version); // TODO check server version (server must support labeled stars and // run notedb) return null; } catch (HttpStatusException e) { return e.getStatusCode() + " " + e.getStatusText(); } catch (RestApiException e) { // server not reachable Log.e(TAG, "Request failed", e); if (e.getCause() != null) { return getString(R.string.error_with_cause, e.getMessage(), e.getCause().getMessage()); } else { return e.getMessage(); } } } private void onServerSave(String serverId) { if (getArguments().get(ORIGIN).equals(IntroFragment2.class)) { ConfigManager cfgManager = getApp().getConfigManager(); cfgManager.setQueryConfig( new QueryConfig.Builder(cfgManager.getQueryConfig()).setServerId(serverId).build()); getApp().getPrefManager() .setPreferences(new Preferences.Builder(getApp().getPrefManager().getPreferences()) .setShowIntro(false).build()); startActivity(new Intent(getContext(), MainActivity.class)); } else { widgetUtil.toast(R.string.server_settings_saved); display(ServerListFragment.class); } } private void displayCredentialsInfo(String url) { if (Strings.isNullOrEmpty(url)) { setGone(v(R.id.crendentialsInfo, R.id.credentialsInfoText, R.id.pasteCredentialsButton)); return; } TextView credentialsInfo = (TextView) v(R.id.credentialsInfoText); credentialsInfo.setMovementMethod(LinkMovementMethod.getInstance()); url = FormatUtil.ensureSlash(url); String host; try { host = new URL(url).getHost(); } catch (MalformedURLException e) { setGone(v(R.id.crendentialsInfo, R.id.credentialsInfoText, R.id.pasteCredentialsButton)); return; } if (host.endsWith(".googlesource.com")) { url += "new-password"; credentialsInfo.setText(Html.fromHtml(getString(R.string.credentials_info_googlesource, createLink(url, getString(R.string.googlesource_obtain_password))))); setVisible(v(R.id.crendentialsInfo, R.id.credentialsInfoText, R.id.pasteCredentialsButton)); } else { url += "#/settings/http-password"; credentialsInfo.setText(Html.fromHtml( getString(R.string.credentials_info, createLink(url, getString(R.string.http_password))))); setGone(v(R.id.pasteCredentialsButton)); setVisible(v(R.id.crendentialsInfo, R.id.credentialsInfoText)); } } private String createLink(String url, String text) { return "<a href=\"" + url + "\">" + text + "</a>"; } private String saveServerSettings() { return getApp().getConfigManager() .setServerConfig(new ServerConfig.Builder().setId(textOf(R.id.idInput)) .setName(textOf(R.id.nameInput)).setUrl(textOf(R.id.urlInput)) .setUser(textOf(R.id.userInput)).setPassword(textOf(R.id.passwordInput)).build()); } }