Add ssh key to user account
This commit is contained in:
parent
b2c51f50dd
commit
b3a0f97ff4
|
@ -9,12 +9,23 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.gitnex.tea4j.v2.models.CreateKeyOption;
|
||||||
|
import org.gitnex.tea4j.v2.models.PublicKey;
|
||||||
|
import org.mian.gitnex.R;
|
||||||
import org.mian.gitnex.adapters.SSHKeysAdapter;
|
import org.mian.gitnex.adapters.SSHKeysAdapter;
|
||||||
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
|
import org.mian.gitnex.databinding.CustomAccountSettingsAddSshKeyBinding;
|
||||||
import org.mian.gitnex.databinding.FragmentAccountSettingsSshKeysBinding;
|
import org.mian.gitnex.databinding.FragmentAccountSettingsSshKeysBinding;
|
||||||
|
import org.mian.gitnex.helpers.Toasty;
|
||||||
import org.mian.gitnex.viewmodels.AccountSettingsSSHKeysViewModel;
|
import org.mian.gitnex.viewmodels.AccountSettingsSSHKeysViewModel;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author M M Arif
|
* @author M M Arif
|
||||||
|
@ -25,6 +36,9 @@ public class SSHKeysFragment extends Fragment {
|
||||||
private Context context;
|
private Context context;
|
||||||
private SSHKeysAdapter adapter;
|
private SSHKeysAdapter adapter;
|
||||||
private AccountSettingsSSHKeysViewModel accountSettingsSSHKeysViewModel;
|
private AccountSettingsSSHKeysViewModel accountSettingsSSHKeysViewModel;
|
||||||
|
private CustomAccountSettingsAddSshKeyBinding newSSHKeyBinding;
|
||||||
|
private MaterialAlertDialogBuilder materialAlertDialogBuilder;
|
||||||
|
private AlertDialog dialogSaveKey;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(
|
public View onCreateView(
|
||||||
|
@ -33,6 +47,11 @@ public class SSHKeysFragment extends Fragment {
|
||||||
viewBinding = FragmentAccountSettingsSshKeysBinding.inflate(inflater, container, false);
|
viewBinding = FragmentAccountSettingsSshKeysBinding.inflate(inflater, container, false);
|
||||||
context = getContext();
|
context = getContext();
|
||||||
|
|
||||||
|
assert context != null;
|
||||||
|
materialAlertDialogBuilder =
|
||||||
|
new MaterialAlertDialogBuilder(
|
||||||
|
context, R.style.ThemeOverlay_Material3_Dialog_Alert);
|
||||||
|
|
||||||
accountSettingsSSHKeysViewModel =
|
accountSettingsSSHKeysViewModel =
|
||||||
new ViewModelProvider(this).get(AccountSettingsSSHKeysViewModel.class);
|
new ViewModelProvider(this).get(AccountSettingsSSHKeysViewModel.class);
|
||||||
|
|
||||||
|
@ -51,9 +70,90 @@ public class SSHKeysFragment extends Fragment {
|
||||||
|
|
||||||
fetchDataAsync();
|
fetchDataAsync();
|
||||||
|
|
||||||
|
viewBinding.addNewSSHKey.setOnClickListener(editProperties -> showNewSSHKeyDialog());
|
||||||
|
|
||||||
return viewBinding.getRoot();
|
return viewBinding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showNewSSHKeyDialog() {
|
||||||
|
|
||||||
|
newSSHKeyBinding =
|
||||||
|
CustomAccountSettingsAddSshKeyBinding.inflate(LayoutInflater.from(context));
|
||||||
|
|
||||||
|
View view = newSSHKeyBinding.getRoot();
|
||||||
|
materialAlertDialogBuilder.setView(view);
|
||||||
|
|
||||||
|
newSSHKeyBinding.keyStatus.setOnCheckedChangeListener(
|
||||||
|
(buttonView, isChecked) -> {
|
||||||
|
if (isChecked) {
|
||||||
|
newSSHKeyBinding.keyStatus.setText(
|
||||||
|
getString(R.string.sshKeyStatusReadWrite));
|
||||||
|
} else {
|
||||||
|
newSSHKeyBinding.keyStatus.setText(
|
||||||
|
getString(R.string.sshKeyStatusReadOnly));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
newSSHKeyBinding.save.setOnClickListener(
|
||||||
|
saveKey -> {
|
||||||
|
if (Objects.requireNonNull(newSSHKeyBinding.keyTitle.getText())
|
||||||
|
.toString()
|
||||||
|
.isEmpty()
|
||||||
|
|| Objects.requireNonNull(newSSHKeyBinding.key.getText())
|
||||||
|
.toString()
|
||||||
|
.isEmpty()) {
|
||||||
|
Toasty.error(context, getString(R.string.emptyFields));
|
||||||
|
} else {
|
||||||
|
saveSSHKey(
|
||||||
|
String.valueOf(newSSHKeyBinding.keyTitle.getText()),
|
||||||
|
String.valueOf(newSSHKeyBinding.key.getText()),
|
||||||
|
newSSHKeyBinding.keyStatus.isChecked());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogSaveKey = materialAlertDialogBuilder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveSSHKey(String title, String key, boolean keyStatus) {
|
||||||
|
|
||||||
|
CreateKeyOption createKeyOption = new CreateKeyOption();
|
||||||
|
createKeyOption.setTitle(title);
|
||||||
|
createKeyOption.setKey(key);
|
||||||
|
createKeyOption.setReadOnly(keyStatus);
|
||||||
|
|
||||||
|
Call<PublicKey> saveNewKey =
|
||||||
|
RetrofitClient.getApiInterface(context).userCurrentPostKey(createKeyOption);
|
||||||
|
|
||||||
|
saveNewKey.enqueue(
|
||||||
|
new Callback<>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(
|
||||||
|
@NonNull Call<PublicKey> call,
|
||||||
|
@NonNull retrofit2.Response<PublicKey> response) {
|
||||||
|
|
||||||
|
if (response.code() == 202 || response.code() == 201) {
|
||||||
|
|
||||||
|
dialogSaveKey.dismiss();
|
||||||
|
accountSettingsSSHKeysViewModel.loadKeysList(context);
|
||||||
|
Toasty.success(context, getString(R.string.sshKeySuccess));
|
||||||
|
} else if (response.code() == 422) {
|
||||||
|
|
||||||
|
Toasty.error(context, getString(R.string.sshKeyError));
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Toasty.error(context, getString(R.string.genericError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<PublicKey> call, @NonNull Throwable t) {
|
||||||
|
|
||||||
|
Toasty.error(context, getString(R.string.genericServerResponseError));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private void fetchDataAsync() {
|
private void fetchDataAsync() {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/dimen8dp">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/mainView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/dimen16dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/keyTitleLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:hint="@string/title"
|
||||||
|
android:textColorHint="?attr/hintColor"
|
||||||
|
app:boxBackgroundColor="?attr/inputBackgroundColor"
|
||||||
|
app:boxStrokeErrorColor="@color/darkRed"
|
||||||
|
app:hintTextColor="?attr/hintColor">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/keyTitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?attr/inputTextColor"
|
||||||
|
android:textColorHighlight="?attr/hintColor"
|
||||||
|
android:textColorHint="?attr/hintColor"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/keyLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:hint="@string/sshKey"
|
||||||
|
android:textColorHint="?attr/hintColor"
|
||||||
|
app:boxBackgroundColor="?attr/inputBackgroundColor"
|
||||||
|
app:boxStrokeErrorColor="@color/darkRed"
|
||||||
|
app:hintTextColor="?attr/hintColor">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/key"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="top|start"
|
||||||
|
android:minHeight="@dimen/dimen180dp"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:textColor="?attr/inputTextColor"
|
||||||
|
android:textColorHighlight="?attr/hintColor"
|
||||||
|
android:textColorHint="?attr/hintColor"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/keyStatus"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/sshKeyStatusReadOnly"
|
||||||
|
android:textColor="?attr/primaryTextColor" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/save"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/dimen54dp"
|
||||||
|
android:layout_marginTop="@dimen/dimen16dp"
|
||||||
|
android:text="@string/saveButton"
|
||||||
|
android:textColor="?attr/materialCardBackgroundColor"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -44,4 +44,17 @@
|
||||||
android:textSize="@dimen/dimen20sp"
|
android:textSize="@dimen/dimen20sp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/addNewSSHKey"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|bottom"
|
||||||
|
android:layout_margin="@dimen/dimen16dp"
|
||||||
|
android:text="@string/addSSHKey"
|
||||||
|
android:contentDescription="@string/addSSHKey"
|
||||||
|
android:textColor="?attr/materialCardBackgroundColor"
|
||||||
|
app:iconTint="?attr/materialCardBackgroundColor"
|
||||||
|
android:backgroundTint="?attr/fabColor"
|
||||||
|
app:icon="@drawable/ic_add" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
|
@ -373,6 +373,12 @@
|
||||||
<string name="sshKeys">SSH Keys</string>
|
<string name="sshKeys">SSH Keys</string>
|
||||||
<string name="deleteEmailPopupText">This action will permanently delete email %s from your account.</string>
|
<string name="deleteEmailPopupText">This action will permanently delete email %s from your account.</string>
|
||||||
<string name="deleteEmailSuccess">Email deleted successfully</string>
|
<string name="deleteEmailSuccess">Email deleted successfully</string>
|
||||||
|
<string name="addSSHKey">Add SSH Key</string>
|
||||||
|
<string name="sshKeyStatusReadOnly">Read-only Access</string>
|
||||||
|
<string name="sshKeyStatusReadWrite">Read-write Access</string>
|
||||||
|
<string name="sshKey">SSH Key</string>
|
||||||
|
<string name="sshKeySuccess">New SSH key added successfully</string>
|
||||||
|
<string name="sshKeyError">Invalid SSH key or SSH key already exists</string>
|
||||||
<!-- account settings -->
|
<!-- account settings -->
|
||||||
|
|
||||||
<!-- single issue section -->
|
<!-- single issue section -->
|
||||||
|
@ -541,6 +547,7 @@
|
||||||
<string name="none">None</string>
|
<string name="none">None</string>
|
||||||
<string name="main">main</string>
|
<string name="main">main</string>
|
||||||
<string name="license">License</string>
|
<string name="license">License</string>
|
||||||
|
<string name="title">Title</string>
|
||||||
<!-- generic copy -->
|
<!-- generic copy -->
|
||||||
|
|
||||||
<string name="exploreUsers">Explore users</string>
|
<string name="exploreUsers">Explore users</string>
|
||||||
|
|
Loading…
Reference in New Issue