/*
- * Copyright (C) 2012-2016 Tobias Brunner
+ * Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* HSR Hochschule fuer Technik Rapperswil
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
private int mColorStateSuccess;
private Button mActionButton;
private ProgressBar mProgress;
- private AlertDialog mErrorDialog;
+ private LinearLayout mErrorView;
+ private TextView mErrorText;
+ private Button mErrorDetails;
+ private Button mDismissError;
private long mErrorConnectionID;
private VpnStateService mService;
private final ServiceConnection mServiceConnection = new ServiceConnection()
});
enableActionButton(null);
+ mErrorView = view.findViewById(R.id.vpn_error);
+ mErrorText = view.findViewById(R.id.vpn_error_text);
+ mErrorDetails = view.findViewById(R.id.error_details);
+ mDismissError = view.findViewById(R.id.dismiss_error);
mProgress = (ProgressBar)view.findViewById(R.id.progress);
mStateView = (TextView)view.findViewById(R.id.vpn_state);
mColorStateBase = mStateView.getCurrentTextColor();
mProfileView = (TextView)view.findViewById(R.id.vpn_profile_label);
mProfileNameView = (TextView)view.findViewById(R.id.vpn_profile_name);
+ mDismissError.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ clearError();
+ }
+ });
+
return view;
}
{
mService.unregisterListener(this);
}
- hideErrorDialog();
}
@Override
{
if (error == ErrorState.NO_ERROR)
{
- hideErrorDialog();
+ mErrorView.setVisibility(View.GONE);
return false;
}
- else if (mErrorDialog != null)
- { /* we already show the dialog */
- return true;
- }
+
mErrorConnectionID = connectionID;
mProfileNameView.setText(name);
showProfile(true);
case AUTH_FAILED:
if (imcState == ImcState.BLOCK)
{
- showErrorDialog(R.string.error_assessment_failed);
+ showError(R.string.error_assessment_failed);
}
else
{
- showErrorDialog(R.string.error_auth_failed);
+ showError(R.string.error_auth_failed);
}
break;
case PEER_AUTH_FAILED:
- showErrorDialog(R.string.error_peer_auth_failed);
+ showError(R.string.error_peer_auth_failed);
break;
case LOOKUP_FAILED:
- showErrorDialog(R.string.error_lookup_failed);
+ showError(R.string.error_lookup_failed);
break;
case UNREACHABLE:
- showErrorDialog(R.string.error_unreachable);
+ showError(R.string.error_unreachable);
break;
default:
- showErrorDialog(R.string.error_generic);
+ showError(R.string.error_generic);
break;
}
return true;
mActionButton.setVisibility(text != null ? View.VISIBLE : View.GONE);
}
- private void hideErrorDialog()
- {
- if (mErrorDialog != null)
- {
- mErrorDialog.dismiss();
- mErrorDialog = null;
- }
- }
-
private void clearError()
{
if (mService != null)
{
- mService.disconnect();
if (mService.getConnectionID() == mErrorConnectionID)
{
+ mService.disconnect();
mService.setError(ErrorState.NO_ERROR);
}
}
updateView();
}
- private void showErrorDialog(int textid)
+ private void showError(int textid)
{
final List<RemediationInstruction> instructions = mService.getRemediationInstructions();
final boolean show_instructions = mService.getImcState() == ImcState.BLOCK && !instructions.isEmpty();
int text = show_instructions ? R.string.show_remediation_instructions : R.string.show_log;
- mErrorDialog = new AlertDialog.Builder(getActivity())
- .setMessage(getString(R.string.error_introduction) + " " + getString(textid))
- .setCancelable(false)
- .setNeutralButton(text, new DialogInterface.OnClickListener()
+ mErrorText.setText(getString(R.string.error_introduction) + " " + getString(textid));
+ mErrorDetails.setText(text);
+ mErrorDetails.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
{
- @Override
- public void onClick(DialogInterface dialog, int which)
+ Intent intent;
+ if (show_instructions)
{
- clearError();
- dialog.dismiss();
- Intent intent;
- if (show_instructions)
- {
- intent = new Intent(getActivity(), RemediationInstructionsActivity.class);
- intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS,
- new ArrayList<RemediationInstruction>(instructions));
- }
- else
- {
- intent = new Intent(getActivity(), LogActivity.class);
- }
- startActivity(intent);
+ intent = new Intent(getActivity(), RemediationInstructionsActivity.class);
+ intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS,
+ new ArrayList<RemediationInstruction>(instructions));
}
- })
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
- {
- @Override
- public void onClick(DialogInterface dialog, int id)
+ else
{
- clearError();
- dialog.dismiss();
+ intent = new Intent(getActivity(), LogActivity.class);
}
- }).create();
- mErrorDialog.setOnDismissListener(new DialogInterface.OnDismissListener()
- {
- @Override
- public void onDismiss(DialogInterface dialog)
- {
- mErrorDialog = null;
+ startActivity(intent);
}
});
- mErrorDialog.show();
+ mErrorView.setVisibility(View.VISIBLE);
}
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 Tobias Brunner
+ HSR Hochschule fuer Technik Rapperswil
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <shape>
+ <solid
+ android:color="@color/panel_separator" />
+ </shape>
+ </item>
+
+ <item android:bottom="2dp">
+ <shape>
+ <solid
+ android:color="@android:color/white" />
+ </shape>
+ </item>
+
+</layer-list>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingBottom="2dp"
android:background="@drawable/state_background"
android:orientation="vertical" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingBottom="2dp"
- android:background="@drawable/state_background"
- android:orientation="vertical" >
+ android:orientation="vertical"
+ android:animateLayoutChanges="true" >
- <GridLayout
+ <LinearLayout
+ android:id="@+id/vpn_error"
+ android:visibility="gone"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="10dp"
- android:layout_marginLeft="20dp"
- android:layout_marginRight="20dp"
- android:layout_marginTop="10dp"
- android:columnCount="2"
- android:rowCount="2" >
+ android:layout_height="match_parent"
+ android:background="@drawable/error_background"
+ android:orientation="vertical" >
<TextView
+ android:id="@+id/vpn_error_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="5dp"
- android:gravity="top"
- android:text="@string/state_label"
- android:textColor="?android:textColorPrimary"
- android:textSize="20sp" />
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="24dp"
+ android:layout_marginBottom="12dp"
+ android:text="Failed to establish VPN: Server is unreachable"
+ android:textColor="@color/primary_dark"
+ android:textSize="16sp" />
- <TextView
- android:id="@+id/vpn_state"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="top"
- android:text="@string/state_disabled"
- android:textColor="?android:textColorSecondary"
- android:textSize="20sp" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="8dp"
+ android:orientation="horizontal"
+ android:gravity="end" >
- <TextView
- android:id="@+id/vpn_profile_label"
- android:layout_width="wrap_content"
+ <Button
+ android:id="@+id/dismiss_error"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:text="@string/dismiss"
+ android:textColor="@color/primary"
+ android:textSize="14sp"
+ android:textStyle="bold"
+ style="?android:attr/borderlessButtonStyle" >
+ </Button>
+
+ <Button
+ android:id="@+id/error_details"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/show_log"
+ android:textColor="@color/primary"
+ android:textSize="14sp"
+ android:textStyle="bold"
+ style="?android:attr/borderlessButtonStyle" >
+ </Button>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/state_background"
+ android:orientation="vertical" >
+
+ <GridLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginRight="5dp"
- android:gravity="top"
- android:text="@string/profile_label"
- android:textColor="?android:textColorPrimary"
- android:textSize="20sp"
- android:visibility="gone" >
- </TextView>
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="20dp"
+ android:layout_marginRight="20dp"
+ android:layout_marginTop="10dp"
+ android:columnCount="2"
+ android:rowCount="2" >
- <TextView
- android:id="@+id/vpn_profile_name"
- android:layout_width="wrap_content"
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dp"
+ android:gravity="top"
+ android:text="@string/state_label"
+ android:textColor="?android:textColorPrimary"
+ android:textSize="20sp" />
+
+ <TextView
+ android:id="@+id/vpn_state"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:text="@string/state_disabled"
+ android:textColor="?android:textColorSecondary"
+ android:textSize="20sp" />
+
+ <TextView
+ android:id="@+id/vpn_profile_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dp"
+ android:gravity="top"
+ android:text="@string/profile_label"
+ android:textColor="?android:textColorPrimary"
+ android:textSize="20sp"
+ android:visibility="gone" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/vpn_profile_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:textSize="20sp"
+ android:visibility="gone" >
+ </TextView>
+ </GridLayout>
+
+ <ProgressBar
+ android:id="@+id/progress"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="top"
- android:textSize="20sp"
- android:visibility="gone" >
- </TextView>
- </GridLayout>
-
- <ProgressBar
- android:id="@+id/progress"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="10dp"
- android:layout_marginLeft="20dp"
- android:layout_marginRight="20dp"
- android:indeterminate="true"
- android:visibility="gone"
- style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="20dp"
+ android:layout_marginRight="20dp"
+ android:indeterminate="true"
+ android:visibility="gone"
+ style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
- <Button
- android:id="@+id/action"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="10dp"
- android:layout_marginLeft="20dp"
- android:layout_marginRight="20dp"
- android:text="@string/disconnect"
- style="?android:attr/borderlessButtonStyle" >
- </Button>
+ <Button
+ android:id="@+id/action"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="20dp"
+ android:layout_marginRight="20dp"
+ android:text="@string/disconnect"
+ style="?android:attr/borderlessButtonStyle" >
+ </Button>
+ </LinearLayout>
</LinearLayout>
<string name="state_disconnecting">Trennen…</string>
<string name="state_disabled">Kein aktives Profil</string>
<string name="state_error">Fehler</string>
+ <string name="dismiss">Ausblenden</string>
<!-- IMC state fragment -->
<string name="imc_state_label">Assessment:</string>
<string name="state_disconnecting">Przerywam połączenie…</string>
<string name="state_disabled">Brak aktywnego VPN</string>
<string name="state_error">Błąd</string>
+ <string name="dismiss">Dismiss</string>
<!-- IMC state fragment -->
<string name="imc_state_label">Assessment:</string>
<string name="state_disconnecting">Отключение…</string>
<string name="state_disabled">Нет активных VPN</string>
<string name="state_error">Ошибка</string>
+ <string name="dismiss">Dismiss</string>
<!-- IMC state fragment -->
<string name="imc_state_label">Assessment:</string>
<string name="state_disconnecting">Роз\'єднання…</string>
<string name="state_disabled">Немає активних VPN</string>
<string name="state_error">Помилка</string>
+ <string name="dismiss">Dismiss</string>
<!-- IMC state fragment -->
<string name="imc_state_label">Assessment:</string>
<string name="state_disconnecting">断开连接中…</string>
<string name="state_disabled">无活跃VPN</string>
<string name="state_error">错误</string>
+ <string name="dismiss">Dismiss</string>
<!-- IMC state fragment -->
<string name="imc_state_label">评估详情:</string>
<string name="state_disconnecting">結束連線中…</string>
<string name="state_disabled">無運作中的VPN</string>
<string name="state_error">錯誤</string>
+ <string name="dismiss">Dismiss</string>
<!-- IMC state fragment -->
<string name="imc_state_label">評估詳情:</string>
name="primary">#A2042C</color>
<color
- name="primary_dark">#000000</color>
+ name="primary_dark">#323232</color>
<color
name="error_text">#D9192C</color>
<string name="state_disconnecting">Disconnecting…</string>
<string name="state_disabled">No active VPN</string>
<string name="state_error">Error</string>
+ <string name="dismiss">Dismiss</string>
<!-- IMC state fragment -->
<string name="imc_state_label">Assessment:</string>