improve login url and authkey handling

pull/5/head
Felix Prahl-Kamps 2019-07-14 18:18:54 +02:00
parent 5e3650bcd9
commit 66d586a546
10 changed files with 165 additions and 253 deletions

View File

@ -1,6 +1,7 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavadocReference" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SuspiciousNameCombination" enabled="false" level="WARNING" enabled_by_default="false">
<group names="x,width,left,right" />
<group names="y,height,top,bottom" />

View File

@ -44,8 +44,8 @@ public class ExchangeActivity extends AppCompatActivity {
private CameraFragment cameraFragment;
private CoordinatorLayout rootLayout;
private View qrFrame;
private TextView qrInfo;
private View qrFrame, scanFeedbackView, continueHintView, fragmentContainer;
private TextView scanFeedbackText;
private ImageView qrCode;
private ImageButton prevButton, nextButton;
@ -57,7 +57,7 @@ public class ExchangeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exchange);
setContentView(R.layout.activity_exchange_2);
preferenceManager = PreferenceManager.getInstance(ExchangeActivity.this);
qrCodeGenerator = new QrCodeGenerator(ExchangeActivity.this);
@ -76,10 +76,14 @@ public class ExchangeActivity extends AppCompatActivity {
private void initViews() {
rootLayout = findViewById(R.id.rootLayout);
fragmentContainer = findViewById(R.id.fragmentContainer);
qrFrame = findViewById(R.id.qrFrame);
qrCode = findViewById(R.id.qrCode);
qrInfo = findViewById(R.id.qrInfo);
scanFeedbackView = findViewById(R.id.scanFeedbackView);
scanFeedbackText = findViewById(R.id.scanFeedbackText);
continueHintView = findViewById(R.id.continueHint);
prevButton = findViewById(R.id.prevButton);
prevButton.setOnClickListener(onPrevClicked());
@ -185,7 +189,6 @@ public class ExchangeActivity extends AppCompatActivity {
}
private void setReadQrStatus(ReadQrStatus status) {
currentReadQrStatus = status;
final Drawable drawable;
@ -206,15 +209,31 @@ public class ExchangeActivity extends AppCompatActivity {
break;
default:
drawable = getDrawable(R.drawable.ic_info_outline);
color = getColor(R.color.status_green);
color = getColor(R.color.status_amber);
break;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
qrInfo.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
qrInfo.setCompoundDrawableTintList(ColorStateList.valueOf(color));
scanFeedbackText.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
scanFeedbackText.setCompoundDrawableTintList(ColorStateList.valueOf(color));
if (currentReadQrStatus == ReadQrStatus.SUCCESS) {
continueHintView.setVisibility(View.VISIBLE);
continueHintView.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.white)));
scanFeedbackView.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.white)));
qrFrame.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.white)));
fragmentContainer.animate().alpha(0).setDuration(250).start();
} else {
fragmentContainer.animate().alpha(1).setDuration(250).start();
continueHintView.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.white_80)));
scanFeedbackView.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.white_80)));
qrFrame.setBackgroundTintList(ColorStateList.valueOf(getColor(R.color.white_80)));
}
}
});
}

View File

@ -1,10 +1,10 @@
package lu.circl.mispbump.activities;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@ -14,19 +14,28 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import lu.circl.mispbump.R;
import lu.circl.mispbump.auxiliary.PreferenceManager;
import lu.circl.mispbump.auxiliary.QrCodeGenerator;
import lu.circl.mispbump.fragments.CameraFragment;
import lu.circl.mispbump.models.UploadInformation;
import lu.circl.mispbump.security.DiffieHellman;
public class ExchangeActivity2 extends AppCompatActivity {
private PreferenceManager preferenceManager;
private QrCodeGenerator qrCodeGenerator;
private DiffieHellman diffieHellman;
private UploadInformation uploadInformation;
private CameraFragment cameraFragment;
private Bitmap publicKeyQr, dataQr;
private TextView titleView, hintView;
private View fragmentContainer;
private ImageView qrCode;
private ImageButton prevButton, nextButton, qrInfoButton;
private CameraFragment cameraFragment;
private boolean isDone = false;
@ -39,13 +48,16 @@ public class ExchangeActivity2 extends AppCompatActivity {
initViews();
initCamera();
}
private void initViews() {
titleView = findViewById(R.id.title);
fragmentContainer = findViewById(R.id.fragmentContainer);
qrCode = findViewById(R.id.qrCode);
qrCode.setImageBitmap(qrCodeGenerator.generateQrCode("Huhu hier steht nix aber auch nicht so wenig denn hier soll mal ein bisschen content im qr code stehen damit es auch realistisch ist...."));
qrCode.setImageBitmap(qrCodeGenerator.generateQrCode("Sample content"));
prevButton = findViewById(R.id.prevButton);
prevButton.setOnClickListener(new View.OnClickListener() {
@ -73,8 +85,8 @@ public class ExchangeActivity2 extends AppCompatActivity {
private void toggleLayoutChange(final boolean done) {
final View doneText = findViewById(R.id.doneText);
View constraintLayout = findViewById(R.id.constraintLayout);
final View doneText = findViewById(R.id.scanFeedbackView);
View constraintLayout = findViewById(R.id.qrFrame);
if (done) {
fragmentContainer.animate().alpha(0f).setDuration(250).start();

View File

@ -33,7 +33,6 @@ import lu.circl.mispbump.models.restModels.User;
public class LoginActivity extends AppCompatActivity {
private PreferenceManager preferenceManager;
private MispRestClient mispRestClient;
private ConstraintLayout constraintLayout;
private TextInputLayout serverAutomationKey;
@ -46,7 +45,6 @@ public class LoginActivity extends AppCompatActivity {
setContentView(R.layout.activity_login);
preferenceManager = PreferenceManager.getInstance(this);
mispRestClient = MispRestClient.getInstance(LoginActivity.this);
getWindow().setStatusBarColor(getColor(R.color.colorPrimary));
@ -97,7 +95,6 @@ public class LoginActivity extends AppCompatActivity {
private View.OnClickListener onClickDownload = new View.OnClickListener() {
@Override
public void onClick(View v) {
final String url = Objects.requireNonNull(serverUrl.getEditText()).getText().toString();
final String authkey = Objects.requireNonNull(serverAutomationKey.getEditText()).getText().toString();
@ -120,7 +117,7 @@ public class LoginActivity extends AppCompatActivity {
return;
}
mispRestClient.initMispRestInterface(url);
final MispRestClient mispRestClient = MispRestClient.getInstance(url, authkey);
// display progress bar
progressBar.setVisibility(View.VISIBLE);

View File

@ -46,8 +46,8 @@ public class ProfileActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
mispRestClient = MispRestClient.getInstance(this);
preferenceManager = PreferenceManager.getInstance(this);
mispRestClient = MispRestClient.getInstance(preferenceManager.getServerUrl(), preferenceManager.getAuthKey());
init();
populateInformationViews();

View File

@ -2,14 +2,15 @@ package lu.circl.mispbump.activities;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import lu.circl.mispbump.auxiliary.PreferenceManager;
import lu.circl.mispbump.models.restModels.User;
/**
* This activity navigates to the next activity base on the user status.
* This is the first activity that gets loaded when the user starts the app.
* Starts either the login or home activity.
*/
public class StartUpActivity extends AppCompatActivity {
@ -17,16 +18,13 @@ public class StartUpActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if (isUserLoggedIn()) {
// Intent home = new Intent(this, HomeActivity.class);
// startActivity(home);
// } else {
// Intent login = new Intent(this, LoginActivity.class);
// startActivity(login);
// }
Intent i = new Intent(this, ExchangeActivity2.class);
startActivity(i);
if (isUserLoggedIn()) {
Intent home = new Intent(this, HomeActivity.class);
startActivity(home);
} else {
Intent login = new Intent(this, LoginActivity.class);
startActivity(login);
}
// closes the activity to prevent going back to this (empty) activity
finish();

View File

@ -99,7 +99,7 @@ public class UploadActivity extends AppCompatActivity {
setContentView(R.layout.activity_upload);
preferenceManager = PreferenceManager.getInstance(UploadActivity.this);
restClient = MispRestClient.getInstance(this);
restClient = MispRestClient.getInstance(preferenceManager.getServerUrl(), preferenceManager.getAuthKey());
parseExtra();
initViews();

View File

@ -1,7 +1,8 @@
package lu.circl.mispbump.auxiliary;
import android.annotation.SuppressLint;
import android.content.Context;
import androidx.annotation.NonNull;
import org.json.JSONException;
import org.json.JSONObject;
@ -45,98 +46,25 @@ import retrofit2.converter.gson.GsonConverterFactory;
public class MispRestClient {
public interface AvailableCallback {
void available();
void unavailable(String error);
}
public interface UserCallback {
void success(User user);
void failure(String error);
}
public interface AllUsersCallback {
void success(User[] users);
void failure(String error);
}
public interface OrganisationCallback {
void success(Organisation organisation);
void failure(String error);
}
public interface AllOrganisationsCallback {
void success(Organisation[] organisations);
void failure(String error);
}
public interface ServerCallback {
void success(Server server);
void failure(String error);
}
public interface AllServersCallback {
void success(Server[] servers);
void failure(String error);
}
private static MispRestClient instance;
private PreferenceManager preferenceManager;
private MispRestInterface mispRestInterface;
public static MispRestClient getInstance(Context context) {
public static MispRestClient getInstance(String url, String authkey) {
if (instance == null) {
instance = new MispRestClient(context);
instance = new MispRestClient();
}
instance.initMispRestInterface(url, authkey);
return instance;
}
public static MispRestClient getInstance(Context context, String url) {
if (instance == null) {
instance = new MispRestClient(context, url);
}
return instance;
}
private MispRestClient(Context context) {
this(context, null);
}
/**
* Initializes the rest client to communicate with a MISP instance.
*
* @param context needed to access the preferences for loading credentials
*/
private MispRestClient(Context context, String url) {
preferenceManager = PreferenceManager.getInstance(context);
if (url == null) {
url = preferenceManager.getServerUrl();
}
initMispRestInterface(url);
}
public void initMispRestInterface(String url) {
public void initMispRestInterface(String url, String authkey) {
try {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.client(getCustomClient(true, false))
.client(getCustomClient(true, false, authkey))
.build();
mispRestInterface = retrofit.create(MispRestInterface.class);
@ -151,7 +79,7 @@ public class MispRestClient {
* @param logging whether to log Retrofit calls (for debugging)
* @return {@link OkHttpClient}
*/
private OkHttpClient getCustomClient(boolean unsafe, boolean logging) {
private OkHttpClient getCustomClient(boolean unsafe, boolean logging, final String authkey) {
try {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
@ -206,7 +134,7 @@ public class MispRestClient {
Request.Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Accept", "application/json");
ongoing.addHeader("Content-Type", "application/json");
ongoing.addHeader("Authorization", preferenceManager.getAutomationKey());
ongoing.addHeader("Authorization", authkey);
return chain.proceed(ongoing.build());
}
});
@ -228,7 +156,7 @@ public class MispRestClient {
Call<Version> call = mispRestInterface.pyMispVersion();
call.enqueue(new Callback<Version>() {
@Override
public void onResponse(Call<Version> call, Response<Version> response) {
public void onResponse(@NonNull Call<Version> call, @NonNull Response<Version> response) {
if (!response.isSuccessful()) {
if (response.code() == 403) {
callback.available();
@ -242,7 +170,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<Version> call, Throwable t) {
public void onFailure(@NonNull Call<Version> call, @NonNull Throwable t) {
callback.unavailable(extractError(t));
}
});
@ -259,7 +187,7 @@ public class MispRestClient {
call.enqueue(new Callback<MispUser>() {
@Override
public void onResponse(Call<MispUser> call, Response<MispUser> response) {
public void onResponse(@NonNull Call<MispUser> call, @NonNull Response<MispUser> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -272,7 +200,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<MispUser> call, Throwable t) {
public void onFailure(@NonNull Call<MispUser> call, @NonNull Throwable t) {
t.printStackTrace();
callback.failure(t.getMessage());
}
@ -291,7 +219,7 @@ public class MispRestClient {
call.enqueue(new Callback<MispUser>() {
@Override
public void onResponse(Call<MispUser> call, Response<MispUser> response) {
public void onResponse(@NonNull Call<MispUser> call, @NonNull Response<MispUser> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -304,7 +232,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<MispUser> call, Throwable t) {
public void onFailure(@NonNull Call<MispUser> call, @NonNull Throwable t) {
t.printStackTrace();
callback.failure(t.getMessage());
}
@ -337,7 +265,7 @@ public class MispRestClient {
call.enqueue(new Callback<List<MispUser>>() {
@Override
public void onResponse(Call<List<MispUser>> call, Response<List<MispUser>> response) {
public void onResponse(@NonNull Call<List<MispUser>> call, @NonNull Response<List<MispUser>> response) {
if (!response.isSuccessful()) {
callback.failure("Failed onResponse");
return;
@ -356,7 +284,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<List<MispUser>> call, Throwable t) {
public void onFailure(@NonNull Call<List<MispUser>> call, @NonNull Throwable t) {
callback.failure(extractError(t));
}
});
@ -373,7 +301,7 @@ public class MispRestClient {
call.enqueue(new Callback<MispUser>() {
@Override
public void onResponse(Call<MispUser> call, Response<MispUser> response) {
public void onResponse(@NonNull Call<MispUser> call, @NonNull Response<MispUser> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -383,7 +311,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<MispUser> call, Throwable t) {
public void onFailure(@NonNull Call<MispUser> call, @NonNull Throwable t) {
callback.failure(t.getMessage());
}
});
@ -403,7 +331,7 @@ public class MispRestClient {
call.enqueue(new Callback<MispOrganisation>() {
@Override
public void onResponse(Call<MispOrganisation> call, Response<MispOrganisation> response) {
public void onResponse(@NonNull Call<MispOrganisation> call, @NonNull Response<MispOrganisation> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -416,7 +344,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<MispOrganisation> call, Throwable t) {
public void onFailure(@NonNull Call<MispOrganisation> call, @NonNull Throwable t) {
callback.failure(t.getMessage());
}
});
@ -448,7 +376,7 @@ public class MispRestClient {
call.enqueue(new Callback<List<MispOrganisation>>() {
@Override
public void onResponse(Call<List<MispOrganisation>> call, Response<List<MispOrganisation>> response) {
public void onResponse(@NonNull Call<List<MispOrganisation>> call, @NonNull Response<List<MispOrganisation>> response) {
if (!response.isSuccessful()) {
// TODO handle
return;
@ -468,7 +396,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<List<MispOrganisation>> call, Throwable t) {
public void onFailure(@NonNull Call<List<MispOrganisation>> call, @NonNull Throwable t) {
callback.failure(extractError(t));
}
});
@ -485,7 +413,7 @@ public class MispRestClient {
call.enqueue(new Callback<MispOrganisation>() {
@Override
public void onResponse(Call<MispOrganisation> call, Response<MispOrganisation> response) {
public void onResponse(@NonNull Call<MispOrganisation> call, @NonNull Response<MispOrganisation> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -495,7 +423,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<MispOrganisation> call, Throwable t) {
public void onFailure(@NonNull Call<MispOrganisation> call, @NonNull Throwable t) {
callback.failure(t.getMessage());
}
});
@ -517,7 +445,7 @@ public class MispRestClient {
call.enqueue(new Callback<List<MispServer>>() {
@Override
public void onResponse(Call<List<MispServer>> call, Response<List<MispServer>> response) {
public void onResponse(@NonNull Call<List<MispServer>> call, @NonNull Response<List<MispServer>> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -536,7 +464,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<List<MispServer>> call, Throwable t) {
public void onFailure(@NonNull Call<List<MispServer>> call, @NonNull Throwable t) {
callback.failure(t.getMessage());
}
});
@ -553,7 +481,7 @@ public class MispRestClient {
call.enqueue(new Callback<Server>() {
@Override
public void onResponse(Call<Server> call, Response<Server> response) {
public void onResponse(@NonNull Call<Server> call, @NonNull Response<Server> response) {
if (!response.isSuccessful()) {
callback.failure(extractError(response));
} else {
@ -562,7 +490,7 @@ public class MispRestClient {
}
@Override
public void onFailure(Call<Server> call, Throwable t) {
public void onFailure(@NonNull Call<Server> call, @NonNull Throwable t) {
callback.failure(t.getMessage());
throw new RuntimeException(t);
}
@ -648,4 +576,48 @@ public class MispRestClient {
return t.getMessage();
}
// interfaces
public interface AvailableCallback {
void available();
void unavailable(String error);
}
public interface UserCallback {
void success(User user);
void failure(String error);
}
public interface AllUsersCallback {
void success(User[] users);
void failure(String error);
}
public interface OrganisationCallback {
void success(Organisation organisation);
void failure(String error);
}
public interface AllOrganisationsCallback {
void success(Organisation[] organisations);
void failure(String error);
}
public interface ServerCallback {
void success(Server server);
void failure(String error);
}
public interface AllServersCallback {
void success(Server[] servers);
void failure(String error);
}
}

View File

@ -210,7 +210,7 @@ public class PreferenceManager {
* @return decrypted automation key associated with the current user. If no user exists an empty
* String is returned.
*/
public String getAutomationKey() {
public String getAuthKey() {
if (!preferences.contains(AUTOMATION_KEY)) {
return "";
@ -284,12 +284,12 @@ public class PreferenceManager {
public String getServerUrl() {
if (!preferences.contains(SERVER_URL)) {
return "";
return null;
}
try {
KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.SERVER_URL_ALIAS);
return keyStoreWrapper.decrypt(preferences.getString(SERVER_URL, ""));
return keyStoreWrapper.decrypt(preferences.getString(SERVER_URL, null));
} catch (NoSuchPaddingException e) {
e.printStackTrace();
@ -305,7 +305,7 @@ public class PreferenceManager {
e.printStackTrace();
}
return "";
return null;
}
/**

View File

@ -29,11 +29,12 @@
app:layout_constraintBottom_toTopOf="@id/navbar_bottom">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:id="@+id/qrFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="32dp"
android:layout_marginTop="8dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:background="@drawable/rect_rounded"
android:backgroundTint="@color/white_80"
app:layout_constraintEnd_toEndOf="parent"
@ -77,37 +78,20 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:visibility="gone"
android:id="@+id/qrCodeInfo"
android:background="@color/white"
android:text="This is what the qr code looks like in text, mayber there is much more but I dont know about this shit."
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintBottom_toTopOf="@+id/qrInfoButton"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/doneText"
android:alpha="1"
android:id="@+id/scanFeedbackView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:background="@drawable/rect_rounded"
android:backgroundTint="@color/white_80">
<TextView
android:id="@+id/scanFeedbackText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
@ -119,101 +103,29 @@
android:text="Public key received"/>
</LinearLayout>
<LinearLayout
android:visibility="gone"
android:id="@+id/continueHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:background="@drawable/rect_rounded"
android:backgroundTint="@color/white_80">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:drawableStart="@drawable/ic_info_outline"
android:drawableTint="@color/status_amber"
android:drawablePadding="8dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:gravity="center_vertical"
android:text="Continue if your partner scanned this QR code"/>
</LinearLayout>
</LinearLayout>
<!--<androidx.constraintlayout.widget.ConstraintLayout-->
<!--android:id="@+id/constraintLayout"-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_margin="32dp"-->
<!--android:layout_marginTop="8dp"-->
<!--android:background="@drawable/rect_rounded"-->
<!--android:backgroundTint="@color/white_80"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--app:layout_constraintTop_toTopOf="parent"-->
<!--app:layout_constraintBottom_toTopOf="@id/navbar_bottom">-->
<!--<TextView-->
<!--android:id="@+id/qrInfoText"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="Public Key"-->
<!--android:textAlignment="center"-->
<!--android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"-->
<!--android:textColor="@color/black"-->
<!--app:layout_constraintBottom_toBottomOf="parent"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--app:layout_constraintTop_toBottomOf="@id/qrCode" />-->
<!--<ImageButton-->
<!--android:id="@+id/qrInfoButton"-->
<!--android:layout_width="48dp"-->
<!--android:layout_height="48dp"-->
<!--android:background="?attr/selectableItemBackgroundBorderless"-->
<!--android:src="@drawable/ic_info_outline"-->
<!--android:tint="@color/black"-->
<!--app:layout_constraintBottom_toBottomOf="parent"-->
<!--app:layout_constraintEnd_toEndOf="parent" />-->
<!--<ImageView-->
<!--android:id="@+id/qrCode"-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="0dp"-->
<!--android:layout_marginStart="12dp"-->
<!--android:layout_marginTop="12dp"-->
<!--android:layout_marginEnd="12dp"-->
<!--android:src="@color/white"-->
<!--app:layout_constraintBottom_toTopOf="@+id/qrInfoButton"-->
<!--app:layout_constraintDimensionRatio="1:1"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--app:layout_constraintTop_toTopOf="parent" />-->
<!--<TextView-->
<!--android:visibility="gone"-->
<!--android:id="@+id/qrCodeInfo"-->
<!--android:background="@color/white"-->
<!--android:text="This is what the qr code looks like in text, mayber there is much more but I dont know about this shit."-->
<!--android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="0dp"-->
<!--android:layout_marginStart="12dp"-->
<!--android:layout_marginTop="12dp"-->
<!--android:layout_marginEnd="12dp"-->
<!--app:layout_constraintBottom_toTopOf="@+id/qrInfoButton"-->
<!--app:layout_constraintDimensionRatio="1:1"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--app:layout_constraintTop_toTopOf="parent" />-->
<!--</androidx.constraintlayout.widget.ConstraintLayout>-->
<!--<LinearLayout-->
<!--android:alpha="0"-->
<!--android:id="@+id/doneText"-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_marginTop="0dp"-->
<!--app:layout_constraintBottom_toTopOf="@id/navbar_bottom"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--android:background="@drawable/rect_rounded"-->
<!--android:backgroundTint="@color/white_80">-->
<!--<TextView-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:padding="16dp"-->
<!--android:drawableStart="@drawable/ic_check_outline"-->
<!--android:drawableTint="@color/status_green"-->
<!--android:drawablePadding="8dp"-->
<!--android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"-->
<!--android:gravity="center_vertical"-->
<!--android:text="Public key received"/>-->
<!--</LinearLayout>-->
<LinearLayout
android:id="@+id/navbar_bottom"
android:layout_width="0dp"
@ -237,6 +149,7 @@
app:srcCompat="@drawable/ic_arrow_back" />
<TextView
android:visibility="invisible"
android:id="@+id/hint"
android:layout_width="0dp"
android:layout_height="wrap_content"