- Basic Login
This commit is contained in:
parent
fbbbaf919e
commit
654e2be933
@ -1,3 +1,7 @@
|
|||||||
|
### Version 1.0.20 Tag: v1.0.20 (2019-01-02)
|
||||||
|
* Added basic login framework
|
||||||
|
* AR Strings update (@rex07)
|
||||||
|
|
||||||
### Version 1.0.19 Tag: v1.0.19 (2018-12-31)
|
### Version 1.0.19 Tag: v1.0.19 (2018-12-31)
|
||||||
* Video Language Filter (@lishoujun)
|
* Video Language Filter (@lishoujun)
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ android {
|
|||||||
applicationId "net.schueller.peertube"
|
applicationId "net.schueller.peertube"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 1019
|
versionCode 1020
|
||||||
versionName "1.0.19"
|
versionName "1.0.20"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
@ -29,16 +29,28 @@ import android.util.Log;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
|
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
|
||||||
import com.mikepenz.iconics.IconicsDrawable;
|
import com.mikepenz.iconics.IconicsDrawable;
|
||||||
|
|
||||||
import net.schueller.peertube.R;
|
import net.schueller.peertube.R;
|
||||||
|
import net.schueller.peertube.helper.APIUrlHelper;
|
||||||
|
import net.schueller.peertube.model.Me;
|
||||||
|
import net.schueller.peertube.model.OauthClient;
|
||||||
|
import net.schueller.peertube.model.Token;
|
||||||
|
import net.schueller.peertube.network.AuthenticationService;
|
||||||
|
import net.schueller.peertube.network.GetUserService;
|
||||||
|
import net.schueller.peertube.network.RetrofitInstance;
|
||||||
import net.schueller.peertube.network.Session;
|
import net.schueller.peertube.network.Session;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.SearchView;
|
import androidx.appcompat.widget.SearchView;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
|
import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
|
||||||
import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
|
import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
|
||||||
@ -46,6 +58,8 @@ import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
|
|||||||
public class AccountActivity extends AppCompatActivity {
|
public class AccountActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|
||||||
|
private static final String TAG = "AccountActivity";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
MenuInflater inflater = getMenuInflater();
|
MenuInflater inflater = getMenuInflater();
|
||||||
@ -70,6 +84,7 @@ public class AccountActivity extends AppCompatActivity {
|
|||||||
Intent intent = new Intent(this, LoginActivity.class);
|
Intent intent = new Intent(this, LoginActivity.class);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
this.startActivity(intent);
|
this.startActivity(intent);
|
||||||
|
finish();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -78,6 +93,12 @@ public class AccountActivity extends AppCompatActivity {
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSupportNavigateUp() {
|
||||||
|
finish(); // close this activity as oppose to navigating up
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -93,10 +114,16 @@ public class AccountActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
setContentView(R.layout.activity_account);
|
setContentView(R.layout.activity_account);
|
||||||
|
|
||||||
|
|
||||||
// Attaching the layout to the toolbar object
|
// Attaching the layout to the toolbar object
|
||||||
Toolbar toolbar = findViewById(R.id.tool_bar_user);
|
Toolbar toolbar = findViewById(R.id.tool_bar_user);
|
||||||
// Setting toolbar as the ActionBar with setSupportActionBar() call
|
// Setting toolbar as the ActionBar with setSupportActionBar() call
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
getSupportActionBar().setHomeAsUpIndicator(
|
||||||
|
new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -110,7 +137,41 @@ public class AccountActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
return false;
|
|
||||||
|
String apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
|
||||||
|
|
||||||
|
GetUserService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class);
|
||||||
|
|
||||||
|
Call<Me> call = service.getMe();
|
||||||
|
|
||||||
|
call.enqueue(new Callback<Me>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<Me> call, @NonNull Response<Me> response) {
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
|
||||||
|
Me me = response.body();
|
||||||
|
|
||||||
|
TextView username = findViewById(R.id.account_username);
|
||||||
|
TextView email = findViewById(R.id.account_email);
|
||||||
|
|
||||||
|
username.setText(me.getUsername());
|
||||||
|
email.setText(me.getEmail());
|
||||||
|
|
||||||
|
Log.v(TAG, me.getEmail());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Me> call, Throwable t) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,6 +27,10 @@ import android.util.Log;
|
|||||||
import android.widget.AutoCompleteTextView;
|
import android.widget.AutoCompleteTextView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
|
||||||
|
import com.mikepenz.iconics.IconicsDrawable;
|
||||||
|
|
||||||
import net.schueller.peertube.R;
|
import net.schueller.peertube.R;
|
||||||
import net.schueller.peertube.helper.APIUrlHelper;
|
import net.schueller.peertube.helper.APIUrlHelper;
|
||||||
@ -37,6 +41,7 @@ import net.schueller.peertube.network.RetrofitInstance;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
@ -73,8 +78,24 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
mEmailView = findViewById(R.id.email);
|
mEmailView = findViewById(R.id.email);
|
||||||
mPasswordView = findViewById(R.id.password);
|
mPasswordView = findViewById(R.id.password);
|
||||||
|
|
||||||
|
|
||||||
|
// Attaching the layout to the toolbar object
|
||||||
|
Toolbar toolbar = findViewById(R.id.tool_bar_login);
|
||||||
|
// Setting toolbar as the ActionBar with setSupportActionBar() call
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
getSupportActionBar().setHomeAsUpIndicator(
|
||||||
|
new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSupportNavigateUp() {
|
||||||
|
finish(); // close this activity as oppose to navigating up
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void attemptLogin() {
|
private void attemptLogin() {
|
||||||
|
|
||||||
@ -139,8 +160,13 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
|
|
||||||
|
finish(); // close this activity
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.wtf(TAG, response2.toString());
|
Log.wtf(TAG, response2.toString());
|
||||||
|
|
||||||
|
Toast.makeText(LoginActivity.this, "Login Error!", Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ public class AuthorizationInterceptor implements Interceptor {
|
|||||||
public AuthorizationInterceptor() {
|
public AuthorizationInterceptor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response intercept(Chain chain) throws IOException {
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
|
||||||
@ -41,18 +43,20 @@ public class AuthorizationInterceptor implements Interceptor {
|
|||||||
|
|
||||||
if (session.isLoggedIn()) {
|
if (session.isLoggedIn()) {
|
||||||
|
|
||||||
if (mainResponse.code() == 401 || mainResponse.code() == 403) {
|
|
||||||
// session.invalidate();
|
|
||||||
// return mainResponse;
|
|
||||||
Log.v("Authorization", "Intercept code: " + mainResponse.code());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// add authentication header to each request if we are logged in
|
// add authentication header to each request if we are logged in
|
||||||
Request.Builder builder = mainRequest.newBuilder().header("Authorization", session.getToken()).
|
Request.Builder builder = mainRequest.newBuilder().header("Authorization", session.getToken()).
|
||||||
method(mainRequest.method(), mainRequest.body());
|
method(mainRequest.method(), mainRequest.body());
|
||||||
|
// Log.v("Authorization", "Intercept: " + session.getToken());
|
||||||
|
|
||||||
|
// build request
|
||||||
mainResponse = chain.proceed(builder.build());
|
mainResponse = chain.proceed(builder.build());
|
||||||
Log.v("Authorization", "Intercept: " + session.getToken());
|
|
||||||
|
// logout on auth error
|
||||||
|
if (mainResponse.code() == 401 || mainResponse.code() == 403) {
|
||||||
|
session.invalidate();
|
||||||
|
Log.v("Authorization", "Intercept: Logout forced");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mainResponse;
|
return mainResponse;
|
||||||
|
@ -11,7 +11,7 @@ import retrofit2.http.Query;
|
|||||||
public interface GetUserService {
|
public interface GetUserService {
|
||||||
|
|
||||||
@GET("users/me")
|
@GET("users/me")
|
||||||
Call<Me> getMe(@Header("Authorization") String authorization);
|
Call<Me> getMe();
|
||||||
|
|
||||||
@GET("users/me/subscriptions/videos")
|
@GET("users/me/subscriptions/videos")
|
||||||
Call<VideoList> getVideosSubscripions(
|
Call<VideoList> getVideosSubscripions(
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
tools:context=".activity.AccountActivity">
|
tools:context=".activity.AccountActivity"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/appbar_user"
|
android:id="@+id/appbar_user"
|
||||||
@ -22,4 +23,26 @@
|
|||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout >
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_marginBottom="0dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/account_username"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/account_email"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -3,74 +3,93 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/activity_vertical_margin"
|
|
||||||
tools:context="net.schueller.peertube.activity.LoginActivity">
|
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appbar_login"
|
||||||
<ScrollView
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/login_form"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/tool_bar_login"
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/email_login_form"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:elevation="4dp" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
tools:context="net.schueller.peertube.activity.LoginActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/login_form"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent">
|
||||||
android:text="Alpha! Login is still in heavy development and may not work correctly!"/>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<LinearLayout
|
||||||
android:id="@+id/email"
|
android:id="@+id/email_login_form"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/prompt_email"
|
|
||||||
android:inputType="textEmailAddress"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:singleLine="true" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/password"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/prompt_password"
|
|
||||||
android:imeActionId="6"
|
|
||||||
android:imeActionLabel="@string/action_sign_in_short"
|
|
||||||
android:imeOptions="actionUnspecified"
|
|
||||||
android:inputType="textPassword"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:singleLine="true" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/email_sign_in_button"
|
|
||||||
style="?android:textAppearanceSmall"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:orientation="vertical">
|
||||||
android:text="@string/action_sign_in"
|
|
||||||
android:textStyle="bold" />
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
</LinearLayout>
|
android:layout_width="match_parent"
|
||||||
</ScrollView>
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Alpha! Login is still in heavy development and may not work correctly!" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<AutoCompleteTextView
|
||||||
|
android:id="@+id/email"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/prompt_email"
|
||||||
|
android:inputType="textEmailAddress"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:singleLine="true" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/password"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/prompt_password"
|
||||||
|
android:imeActionId="6"
|
||||||
|
android:imeActionLabel="@string/action_sign_in_short"
|
||||||
|
android:imeOptions="actionUnspecified"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:singleLine="true" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/email_sign_in_button"
|
||||||
|
style="?android:textAppearanceSmall"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/action_sign_in"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
Loading…
Reference in New Issue
Block a user