Reviewed-on: https://git.bubblev.org/bubblev/bubble-droid/pulls/10pull/11/head
@@ -35,15 +35,17 @@ | |||
android:label="@string/app_name" | |||
android:roundIcon="@mipmap/ic_launcher_round" | |||
android:supportsRtl="true" | |||
android:theme="@style/AppTheme"> | |||
<activity android:name=".activity.MainActivity"> | |||
android:theme="@style/BubbleTheme"> | |||
<activity android:name=".activity.MainActivity" | |||
android:screenOrientation="portrait"> | |||
<intent-filter> | |||
<action android:name="android.intent.action.MAIN" /> | |||
<category android:name="android.intent.category.LAUNCHER" /> | |||
</intent-filter> | |||
</activity> | |||
<activity android:name=".activity.LoginActivity" /> | |||
<activity android:name=".activity.LoginActivity" | |||
android:screenOrientation="portrait"/> | |||
<activity | |||
android:name=".activity.TunnelToggleActivity" | |||
android:theme="@style/NoBackgroundTheme" /> | |||
@@ -1,42 +1,47 @@ | |||
package com.wireguard.android.activity; | |||
import androidx.annotation.NonNull; | |||
import androidx.annotation.Nullable; | |||
import androidx.appcompat.widget.AppCompatButton; | |||
import androidx.lifecycle.Observer; | |||
import androidx.lifecycle.ViewModelProvider; | |||
import android.content.Intent; | |||
import android.os.Bundle; | |||
import android.security.KeyChain; | |||
import android.text.Editable; | |||
import android.text.TextWatcher; | |||
import android.util.Log; | |||
import android.view.View; | |||
import android.view.View.OnClickListener; | |||
import android.widget.Button; | |||
import android.widget.EditText; | |||
import android.widget.Toast; | |||
import com.wireguard.android.R; | |||
import com.wireguard.android.model.User; | |||
import com.wireguard.android.repository.DataRepository; | |||
import com.wireguard.android.resource.StatusResource; | |||
import com.wireguard.android.viewmodel.LoginViewModel; | |||
import javax.security.cert.CertificateEncodingException; | |||
import javax.security.cert.CertificateException; | |||
import javax.security.cert.X509Certificate; | |||
public class LoginActivity extends BaseActivityBubble { | |||
private LoginViewModel loginViewModel; | |||
private EditText bubbleName; | |||
private EditText userName; | |||
private EditText password; | |||
private Button sign; | |||
private AppCompatButton sign; | |||
private static final String BASE_URL_PREFIX = "https://"; | |||
private static final String BASE_URL_SUFFIX = ":1443/api/"; | |||
private static final String SEPARATOR = "\\."; | |||
private static final int REQUEST_CODE = 1555; | |||
private static final String CERTIFICATE_NAME = "Bubble Certificate"; | |||
private boolean bubbleNameStateFlag = false; | |||
private boolean userNameStateFlag = false; | |||
private boolean passwordStateFlag = false; | |||
private static final String BUBBLE_NAME_KEY = "bubbleName"; | |||
private static final String USER_NAME_KEY = "userName"; | |||
private static final String PASSWORD_KEY = "password"; | |||
@Override | |||
protected void onCreate(Bundle savedInstanceState) { | |||
@@ -71,8 +76,12 @@ public class LoginActivity extends BaseActivityBubble { | |||
login(usernameInput, passwordInput); | |||
} | |||
}); | |||
bubbleNameStateListener(); | |||
userNameStateListener(); | |||
passwordStateListener(); | |||
} | |||
private void initViews() { | |||
bubbleName = findViewById(R.id.bubbleName); | |||
userName = findViewById(R.id.userName); | |||
@@ -80,6 +89,84 @@ public class LoginActivity extends BaseActivityBubble { | |||
sign = findViewById(R.id.signButton); | |||
} | |||
private void bubbleNameStateListener() { | |||
bubbleName.addTextChangedListener(new TextWatcher() { | |||
@Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { | |||
} | |||
@Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { | |||
} | |||
@Override public void afterTextChanged(final Editable s) { | |||
if (bubbleName.getText().toString().trim().isEmpty()) { | |||
bubbleNameStateFlag = false; | |||
} else { | |||
bubbleNameStateFlag = true; | |||
} | |||
setButtonState(); | |||
} | |||
}); | |||
} | |||
private void userNameStateListener() { | |||
userName.addTextChangedListener(new TextWatcher() { | |||
@Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { | |||
} | |||
@Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { | |||
} | |||
@Override public void afterTextChanged(final Editable s) { | |||
if (userName.getText().toString().trim().isEmpty()) { | |||
userNameStateFlag = false; | |||
} else { | |||
userNameStateFlag = true; | |||
} | |||
setButtonState(); | |||
} | |||
}); | |||
} | |||
private void passwordStateListener() { | |||
password.addTextChangedListener(new TextWatcher() { | |||
@Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { | |||
} | |||
@Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { | |||
} | |||
@Override public void afterTextChanged(final Editable s) { | |||
if (password.getText().toString().trim().isEmpty()) { | |||
passwordStateFlag = false; | |||
} else { | |||
passwordStateFlag = true; | |||
} | |||
setButtonState(); | |||
} | |||
}); | |||
} | |||
private void setButtonState(){ | |||
if(userNameStateFlag && bubbleNameStateFlag && passwordStateFlag){ | |||
sign.setBackgroundDrawable(getDrawable(R.drawable.sign_in_enable)); | |||
sign.setEnabled(true); | |||
} | |||
else { | |||
sign.setBackgroundDrawable(getDrawable(R.drawable.sign_in_button)); | |||
sign.setEnabled(false); | |||
} | |||
} | |||
private void login(String username, String password) { | |||
loginViewModel.login(username, password, this).observe(this, new Observer<StatusResource<User>>() { | |||
@Override public void onChanged(final StatusResource<User> userStatusResource) { | |||
@@ -124,4 +211,18 @@ public class LoginActivity extends BaseActivityBubble { | |||
Toast.makeText(this, getString(R.string.cerificate_install), Toast.LENGTH_LONG).show(); | |||
} | |||
} | |||
@Override protected void onSaveInstanceState(@NonNull final Bundle outState) { | |||
outState.putBoolean(BUBBLE_NAME_KEY,bubbleNameStateFlag); | |||
outState.putBoolean(USER_NAME_KEY,userNameStateFlag); | |||
outState.putBoolean(PASSWORD_KEY,passwordStateFlag); | |||
super.onSaveInstanceState(outState); | |||
} | |||
@Override protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) { | |||
bubbleNameStateFlag = savedInstanceState.getBoolean(BUBBLE_NAME_KEY); | |||
userNameStateFlag = savedInstanceState.getBoolean(USER_NAME_KEY); | |||
passwordStateFlag = savedInstanceState.getBoolean(PASSWORD_KEY); | |||
super.onRestoreInstanceState(savedInstanceState); | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview_background_shape"> | |||
<stroke android:width="2dp" android:color="#E3E3E4" /> | |||
<padding android:left="2dp" | |||
android:top="2dp" | |||
android:right="2dp" | |||
android:bottom="2dp" /> | |||
<corners android:radius="5dp" /> | |||
<solid android:color="#ffffffff" /> | |||
</shape> |
@@ -0,0 +1,10 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<item> | |||
<shape android:shape="rectangle"> | |||
<gradient android:endColor="#DF9BDF" android:startColor="#F597C8" /> | |||
<corners android:radius="100dp" /> | |||
</shape> | |||
</item> | |||
</selector> |
@@ -0,0 +1,10 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<item> | |||
<shape android:shape="rectangle"> | |||
<gradient android:endColor="#C037C0" android:startColor="#EC2F91" /> | |||
<corners android:radius="100dp" /> | |||
</shape> | |||
</item> | |||
</selector> |
@@ -4,87 +4,199 @@ | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:background="@color/white" | |||
android:layout_height="match_parent" | |||
tools:context="com.wireguard.android.activity.LoginActivity"> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:id="@+id/imageConstraint" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent"> | |||
<ImageView | |||
android:id="@+id/color_curve" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:layout_alignParentStart="true" | |||
android:layout_alignParentTop="true" | |||
android:background="@color/white" | |||
android:scaleType="fitXY" | |||
android:src="@drawable/color_curves" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.0" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="1.0" /> | |||
<ImageView | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="24dp" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:src="@drawable/bubble_top" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.51" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.0" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
<TextView | |||
android:id="@+id/signIn" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="32dp" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:fontFamily="@font/josefin_sans_bold" | |||
android:text="@string/sign_in" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/imageConstraint" /> | |||
<TextView | |||
android:id="@+id/bubbleNameTitle" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="40dp" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:fontFamily="@font/lato" | |||
android:text="@string/bubble_name" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.105" /> | |||
app:layout_constraintTop_toBottomOf="@+id/signIn" /> | |||
<EditText | |||
android:id="@+id/bubbleName" | |||
android:layout_width="match_parent" | |||
android:layout_width="@dimen/edit_text_width" | |||
android:layout_height="@dimen/edit_text_height" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="@dimen/margin_top" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:background="@drawable/rectangle" | |||
android:hint="@string/enter_your_bubble_name" | |||
android:textAlignment="center" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/bubbleNameTitle" /> | |||
<TextView | |||
android:id="@+id/findBubble" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textSize="18sp" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="@dimen/margin_top" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:fontFamily="@font/lato" | |||
android:text="@string/you_can_find_your_bubble_name_in_your_email" | |||
android:textColor="@color/gray" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.504" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.159" /> | |||
app:layout_constraintTop_toBottomOf="@+id/bubbleName" /> | |||
<TextView | |||
android:id="@+id/emailTitle" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="160dp" | |||
android:text="@string/user_name" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="@dimen/margin_top" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:fontFamily="@font/lato" | |||
android:text="@string/email" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.482" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
app:layout_constraintTop_toBottomOf="@+id/findBubble" /> | |||
<EditText | |||
android:id="@+id/userName" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:textSize="18sp" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:layout_width="@dimen/edit_text_width" | |||
android:layout_height="@dimen/edit_text_height" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="@dimen/margin_top" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:background="@drawable/rectangle" | |||
android:hint="@string/email_you_used_to_sign_up" | |||
android:textAlignment="center" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.504" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.276" /> | |||
app:layout_constraintTop_toBottomOf="@+id/emailTitle" /> | |||
<TextView | |||
android:id="@+id/passwordTitle" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="@dimen/margin_start_and_end" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:fontFamily="@font/lato" | |||
android:text="@string/password" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.472" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.363" /> | |||
app:layout_constraintTop_toBottomOf="@+id/userName" /> | |||
<EditText | |||
android:id="@+id/password" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:inputType="textPassword" | |||
android:textSize="18sp" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:layout_width="@dimen/edit_text_width" | |||
android:layout_height="@dimen/edit_text_height" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="@dimen/margin_top" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:background="@drawable/rectangle" | |||
android:hint="@string/your_password" | |||
android:textAlignment="center" | |||
android:textColor="@color/black" | |||
android:textSize="@dimen/login_text_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.51" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.435" /> | |||
<Button | |||
android:id="@+id/signButton" | |||
android:layout_width="95dp" | |||
android:layout_height="49dp" | |||
android:layout_marginBottom="272dp" | |||
android:background="@color/secondary_color" | |||
android:text="@string/sign_in" | |||
android:textSize="15sp" | |||
app:layout_constraintTop_toBottomOf="@+id/passwordTitle" /> | |||
<LinearLayout | |||
android:id="@+id/linearLayout" | |||
android:layout_width="@dimen/edit_text_width" | |||
android:layout_height="@dimen/edit_text_height" | |||
android:layout_marginStart="@dimen/margin_start_and_end" | |||
android:layout_marginTop="10dp" | |||
android:layout_marginEnd="@dimen/margin_start_and_end" | |||
android:layout_marginBottom="24dp" | |||
android:background="@color/white" | |||
android:orientation="vertical" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" /> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/password"> | |||
<androidx.appcompat.widget.AppCompatButton | |||
android:id="@+id/signButton" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:background="@drawable/sign_in_button" | |||
android:enabled="false" | |||
android:text="@string/sign_in" | |||
android:textAlignment="center" | |||
android:textAllCaps="false" | |||
android:textColor="@color/white" | |||
android:textSize="@dimen/login_text_title" /> | |||
</LinearLayout> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -26,5 +26,12 @@ | |||
<color name="info_tag_color">#00aa00</color> | |||
<color name="warning_tag_color">#aaaa00</color> | |||
<color name="colorPrimaryDark">#C04B26</color> | |||
<!-- <color name="colorPrimaryDark">#C04B26</color>--> | |||
<!--Bubble Colors--> | |||
<color name="black">#333333</color> | |||
<color name="gray">#838383</color> | |||
<color name="colorPrimary">#3F51B5</color> | |||
<color name="colorPrimaryDark">#b5e6ff</color> | |||
<color name="colorAccent">#FF4081</color> | |||
</resources> |
@@ -6,4 +6,12 @@ | |||
<dimen name="normal_margin">8dp</dimen> | |||
<dimen name="bottom_sheet_top_padding">8dp</dimen> | |||
<dimen name="bottom_sheet_icon_padding">16dp</dimen> | |||
<!--Bubble dimens--> | |||
<dimen name="title">24sp</dimen> | |||
<dimen name="login_text_title">14sp</dimen> | |||
<dimen name="margin_start_and_end">16dp</dimen> | |||
<dimen name="margin_top">8dp</dimen> | |||
<dimen name="edit_text_width">254dp</dimen> | |||
<dimen name="edit_text_height">55dp</dimen> | |||
</resources> |
@@ -227,10 +227,10 @@ | |||
<string name="biometric_auth_error">Authentication failure</string> | |||
<string name="biometric_auth_error_reason">Authentication failure: %s</string> | |||
<!--Bubble constants--> | |||
<string name="bubble_name">Bubble Name</string> | |||
<string name="bubble_name">Bubble Name:</string> | |||
<string name="user_name">User Name:</string> | |||
<string name="password">Password:</string> | |||
<string name="sign_in">SIGN IN</string> | |||
<string name="sign_in">Sign In</string> | |||
<string name="don_t_have_a_bubble">Don\'t have a Bubble?</string> | |||
<string name="start_new_bubble">Start New Bubble</string> | |||
<string name="my_bubble">My Bubble</string> | |||
@@ -250,4 +250,9 @@ | |||
<string name="login_failed">Login Failed</string> | |||
<string name="cerificate_install">"Please install a certificate"</string> | |||
<string name="success">Success</string> | |||
<string name="your_password">Your password</string> | |||
<string name="email_you_used_to_sign_up">Email you used to Sign Up</string> | |||
<string name="email">Email:</string> | |||
<string name="you_can_find_your_bubble_name_in_your_email">You can find your Bubble name in your email</string> | |||
<string name="enter_your_bubble_name">Enter your Bubble Name</string> | |||
</resources> |
@@ -1,6 +1,13 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<resources xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<style name="BubbleTheme" parent="Theme.AppCompat.Light.NoActionBar"> | |||
<item name="colorPrimary">@color/colorPrimary</item> | |||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> | |||
<item name="colorAccent">@color/colorAccent</item> | |||
<item name="android:textColorHint">@color/gray</item> | |||
</style> | |||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight"> | |||
<item name="colorPrimary">@color/primary_color</item> | |||
<item name="colorOnPrimary">@color/color_control_normal</item> | |||