Delete email from account and other UI fixes

This commit is contained in:
M M Arif 2024-03-25 22:31:59 +05:00
parent 8aed52b778
commit b2c51f50dd
11 changed files with 171 additions and 36 deletions

View File

@ -58,8 +58,8 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0' implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.compose.material3:material3:1.2.0' implementation 'androidx.compose.material3:material3:1.2.1'
implementation 'androidx.compose.material3:material3-window-size-class:1.2.0' implementation 'androidx.compose.material3:material3-window-size-class:1.2.1'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02' implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0"
@ -108,9 +108,9 @@ dependencies {
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0' implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.github.chrisvest:stormpot:2.4.2' implementation 'com.github.chrisvest:stormpot:2.4.2'
implementation 'androidx.browser:browser:1.7.0' implementation 'androidx.browser:browser:1.8.0'
implementation 'com.google.android.flexbox:flexbox:3.0.0' implementation 'com.google.android.flexbox:flexbox:3.0.0'
implementation('org.codeberg.gitnex:tea4j-autodeploy:4646f53557') { implementation('org.codeberg.gitnex:tea4j-autodeploy:3f8f9fce13') {
exclude module: 'org.apache.oltu.oauth2.common' exclude module: 'org.apache.oltu.oauth2.common'
} }
implementation 'io.github.amrdeveloper:codeview:1.3.9' implementation 'io.github.amrdeveloper:codeview:1.3.9'

View File

@ -274,6 +274,7 @@ public class IssueDetailActivity extends BaseActivity
repoOwner = issue.getRepository().getOwner(); repoOwner = issue.getRepository().getOwner();
repoName = issue.getRepository().getName(); repoName = issue.getRepository().getName();
issueIndex = issue.getIssueIndex(); issueIndex = issue.getIssueIndex();
Boolean isLocked = issue.getIssue().isIsLocked();
setSupportActionBar(viewBinding.toolbar); setSupportActionBar(viewBinding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName); Objects.requireNonNull(getSupportActionBar()).setTitle(repoName);
@ -293,6 +294,12 @@ public class IssueDetailActivity extends BaseActivity
viewBinding.recyclerView.setNestedScrollingEnabled(false); viewBinding.recyclerView.setNestedScrollingEnabled(false);
viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx)); viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
if (isLocked && !issue.getRepository().getPermissions().isAdmin()) {
viewBinding.addNewComment.setVisibility(View.GONE);
} else {
viewBinding.addNewComment.setVisibility(View.VISIBLE);
}
viewBinding.addNewComment.setOnClickListener( viewBinding.addNewComment.setOnClickListener(
v -> { v -> {
BottomSheetReplyFragment bottomSheetReplyFragment = BottomSheetReplyFragment bottomSheetReplyFragment =
@ -1106,7 +1113,7 @@ public class IssueDetailActivity extends BaseActivity
LinearLayout.LayoutParams.WRAP_CONTENT); LinearLayout.LayoutParams.WRAP_CONTENT);
paramsLabels.setMargins(0, 0, 15, 0); paramsLabels.setMargins(0, 0, 15, 0);
if (issue.getIssue().getLabels().size() > 0) { if (!issue.getIssue().getLabels().isEmpty()) {
viewBinding.labelsScrollView.setVisibility(View.VISIBLE); viewBinding.labelsScrollView.setVisibility(View.VISIBLE);
@ -1298,7 +1305,7 @@ public class IssueDetailActivity extends BaseActivity
if (response.code() == 200) { if (response.code() == 200) {
assert attachment != null; assert attachment != null;
if (attachment.size() > 0) { if (!attachment.isEmpty()) {
viewBinding.attachmentFrame.setVisibility(View.VISIBLE); viewBinding.attachmentFrame.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams paramsAttachment = LinearLayout.LayoutParams paramsAttachment =

View File

@ -31,7 +31,6 @@ import retrofit2.Callback;
*/ */
public class RepositorySettingsActivity extends BaseActivity { public class RepositorySettingsActivity extends BaseActivity {
private ActivityRepositorySettingsBinding viewBinding;
private CustomRepositoryEditPropertiesDialogBinding propBinding; private CustomRepositoryEditPropertiesDialogBinding propBinding;
private CustomRepositoryDeleteDialogBinding deleteRepoBinding; private CustomRepositoryDeleteDialogBinding deleteRepoBinding;
private CustomRepositoryTransferDialogBinding transferRepoBinding; private CustomRepositoryTransferDialogBinding transferRepoBinding;
@ -49,11 +48,11 @@ public class RepositorySettingsActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewBinding = ActivityRepositorySettingsBinding.inflate(getLayoutInflater()); org.mian.gitnex.databinding.ActivityRepositorySettingsBinding viewBinding =
ActivityRepositorySettingsBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot()); setContentView(viewBinding.getRoot());
repository = RepositoryContext.fromIntent(getIntent()); repository = RepositoryContext.fromIntent(getIntent());
;
ImageView closeActivity = findViewById(R.id.close); ImageView closeActivity = findViewById(R.id.close);

View File

@ -5,14 +5,22 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat; import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.List; import java.util.List;
import org.gitnex.tea4j.v2.models.DeleteEmailOption;
import org.gitnex.tea4j.v2.models.Email; import org.gitnex.tea4j.v2.models.Email;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Toasty;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/** /**
* @author M M Arif * @author M M Arif
@ -29,23 +37,28 @@ public class AccountSettingsEmailsAdapter
} }
@NonNull @Override @NonNull @Override
public AccountSettingsEmailsAdapter.EmailsViewHolder onCreateViewHolder( public EmailsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@NonNull ViewGroup parent, int viewType) {
View v = View v =
LayoutInflater.from(parent.getContext()) LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_account_settings_emails, parent, false); .inflate(R.layout.list_account_settings_emails, parent, false);
return new AccountSettingsEmailsAdapter.EmailsViewHolder(v); return new EmailsViewHolder(v);
} }
@Override @Override
public void onBindViewHolder( public void onBindViewHolder(@NonNull EmailsViewHolder holder, int position) {
@NonNull AccountSettingsEmailsAdapter.EmailsViewHolder holder, int position) {
Email currentItem = emailsList.get(position); Email currentItem = emailsList.get(position);
holder.userEmail.setText(currentItem.getEmail()); holder.userEmail.setText(currentItem.getEmail());
LinearLayout.LayoutParams param =
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
.1f);
if (currentItem.isPrimary()) { if (currentItem.isPrimary()) {
holder.primaryFrame.setVisibility(View.VISIBLE);
TextDrawable drawable = TextDrawable drawable =
TextDrawable.builder() TextDrawable.builder()
.beginConfig() .beginConfig()
@ -64,9 +77,15 @@ public class AccountSettingsEmailsAdapter
null), null),
8); 8);
holder.emailPrimary.setImageDrawable(drawable); holder.emailPrimary.setImageDrawable(drawable);
holder.deleteFrame.setVisibility(View.GONE);
holder.primaryFrame.setLayoutParams(param);
} else { } else {
holder.emailPrimary.setVisibility(View.GONE); holder.primaryFrame.setVisibility(View.GONE);
holder.deleteFrame.setVisibility(View.VISIBLE);
} }
holder.deleteFrame.setOnClickListener(
delEmail -> deleteEmailAddress(currentItem.getEmail(), position));
} }
@Override @Override
@ -74,16 +93,88 @@ public class AccountSettingsEmailsAdapter
return emailsList.size(); return emailsList.size();
} }
static class EmailsViewHolder extends RecyclerView.ViewHolder { public static class EmailsViewHolder extends RecyclerView.ViewHolder {
private final ImageView emailPrimary; private final ImageView emailPrimary;
private final TextView userEmail; private final TextView userEmail;
private final LinearLayout deleteFrame;
private final LinearLayout primaryFrame;
private EmailsViewHolder(View itemView) { private EmailsViewHolder(View itemView) {
super(itemView); super(itemView);
emailPrimary = itemView.findViewById(R.id.emailPrimary); emailPrimary = itemView.findViewById(R.id.emailPrimary);
userEmail = itemView.findViewById(R.id.userEmail); userEmail = itemView.findViewById(R.id.userEmail);
deleteFrame = itemView.findViewById(R.id.deleteFrame);
primaryFrame = itemView.findViewById(R.id.primaryFrame);
} }
} }
private void updateAdapter(int position) {
emailsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, emailsList.size());
}
private void deleteEmailAddress(final String emailAddress, int position) {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(
context, R.style.ThemeOverlay_Material3_Dialog_Alert);
DeleteEmailOption deleteEmailOption = new DeleteEmailOption();
deleteEmailOption.addEmailsItem(emailAddress);
materialAlertDialogBuilder
.setMessage(
String.format(
context.getString(R.string.deleteEmailPopupText), emailAddress))
.setPositiveButton(
R.string.menuDeleteText,
(dialog, whichButton) ->
RetrofitClient.getApiInterface(context)
.userDeleteEmailWithBody(deleteEmailOption)
.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<Void> call,
@NonNull Response<Void> response) {
if (response.isSuccessful()) {
updateAdapter(position);
Toasty.success(
context,
context.getString(
R.string
.deleteEmailSuccess));
} else if (response.code() == 403) {
Toasty.error(
context,
context.getString(
R.string
.authorizeError));
} else {
Toasty.error(
context,
context.getString(
R.string.genericError));
}
}
@Override
public void onFailure(
@NonNull Call<Void> call,
@NonNull Throwable t) {
Toasty.error(
context,
context.getString(
R.string.genericError));
}
}))
.setNeutralButton(R.string.cancelButton, null)
.show();
}
} }

View File

@ -191,7 +191,7 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
Markdown.render(context, dataModel.getTitle(), msTitle); Markdown.render(context, dataModel.getTitle(), msTitle);
if (!dataModel.getDescription().equals("")) { if (!dataModel.getDescription().isEmpty()) {
Markdown.render( Markdown.render(
context, context,

View File

@ -69,7 +69,7 @@ public class TagsAdapter extends RecyclerView.Adapter<TagsAdapter.TagsViewHolder
holder.tagName.setText(currentItem.getName()); holder.tagName.setText(currentItem.getName());
if (!currentItem.getMessage().equals("")) { if (!currentItem.getMessage().isEmpty()) {
Markdown.render(context, currentItem.getMessage(), holder.tagBody); Markdown.render(context, currentItem.getMessage(), holder.tagBody);
} else { } else {
holder.tagBody.setVisibility(View.GONE); holder.tagBody.setVisibility(View.GONE);
@ -228,7 +228,7 @@ public class TagsAdapter extends RecyclerView.Adapter<TagsAdapter.TagsViewHolder
void onLoadFinished(); void onLoadFinished();
} }
protected class TagsViewHolder extends RecyclerView.ViewHolder { public class TagsViewHolder extends RecyclerView.ViewHolder {
private final TextView tagName; private final TextView tagName;
private final TextView tagBody; private final TextView tagBody;

View File

@ -127,7 +127,9 @@ public class PullRequestCommitsFragment extends Fragment {
issue.getRepository().getName(), issue.getRepository().getName(),
(long) issue.getIssueIndex(), (long) issue.getIssueIndex(),
1, 1,
resultLimit); resultLimit,
null,
null);
call.enqueue( call.enqueue(
new Callback<>() { new Callback<>() {
@ -184,7 +186,9 @@ public class PullRequestCommitsFragment extends Fragment {
issue.getRepository().getName(), issue.getRepository().getName(),
(long) issue.getIssueIndex(), (long) issue.getIssueIndex(),
page, page,
resultLimit); resultLimit,
null,
null);
call.enqueue( call.enqueue(
new Callback<>() { new Callback<>() {

View File

@ -39,7 +39,7 @@ public class ReleasesViewModel extends ViewModel {
Call<List<Release>> call = Call<List<Release>> call =
RetrofitClient.getApiInterface(ctx) RetrofitClient.getApiInterface(ctx)
.repoListReleases(owner, repo, null, null, null, 1, resultLimit); .repoListReleases(owner, repo, null, null, 1, resultLimit);
call.enqueue( call.enqueue(
new Callback<>() { new Callback<>() {
@ -69,7 +69,7 @@ public class ReleasesViewModel extends ViewModel {
Call<List<Release>> call = Call<List<Release>> call =
RetrofitClient.getApiInterface(ctx) RetrofitClient.getApiInterface(ctx)
.repoListReleases(owner, repo, null, null, null, page, resultLimit); .repoListReleases(owner, repo, null, null, page, resultLimit);
call.enqueue( call.enqueue(
new Callback<>() { new Callback<>() {
@ -84,7 +84,7 @@ public class ReleasesViewModel extends ViewModel {
assert list != null; assert list != null;
assert response.body() != null; assert response.body() != null;
if (response.body().size() != 0) { if (!response.body().isEmpty()) {
list.addAll(response.body()); list.addAll(response.body());
adapter.updateList(list); adapter.updateList(list);
} else { } else {
@ -157,7 +157,7 @@ public class ReleasesViewModel extends ViewModel {
assert list != null; assert list != null;
assert response.body() != null; assert response.body() != null;
if (response.body().size() != 0) { if (!response.body().isEmpty()) {
list.addAll(response.body()); list.addAll(response.body());
adapter.updateList(list); adapter.updateList(list);
} else { } else {

View File

@ -105,7 +105,7 @@
android:layout_marginTop="@dimen/dimen16dp" android:layout_marginTop="@dimen/dimen16dp"
android:backgroundTint="@color/darkRed" android:backgroundTint="@color/darkRed"
android:text="@string/repoTransferText" android:text="@string/repoTransferText"
android:textColor="?attr/materialCardBackgroundColor" android:textColor="@color/colorWhite"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold"/> android:textStyle="bold"/>

View File

@ -18,30 +18,62 @@
style="?attr/materialCardViewFilledStyle"> style="?attr/materialCardViewFilledStyle">
<LinearLayout <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor" android:background="?attr/materialCardBackgroundColor"
android:padding="@dimen/dimen12dp" android:padding="@dimen/dimen12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/userEmail" android:id="@+id/userEmail"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight=".7"
android:text="@string/accountEmailTitle" android:text="@string/accountEmailTitle"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"/> android:textSize="@dimen/dimen16sp"/>
<ImageView <LinearLayout
android:id="@+id/emailPrimary" android:id="@+id/primaryFrame"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_weight=".2"
android:layout_marginTop="@dimen/dimen2dp" android:gravity="end"
android:contentDescription="@string/emailTypeText" android:visibility="gone">
android:paddingStart="@dimen/dimen20dp"
android:paddingEnd="@dimen/dimen2dp" <ImageView
tools:src="@drawable/ic_verified_user"/> android:id="@+id/emailPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/dimen2dp"
android:contentDescription="@string/emailTypeText"
android:paddingStart="@dimen/dimen2dp"
android:paddingEnd="@dimen/dimen2dp"
tools:src="@drawable/ic_verified_user" />
</LinearLayout>
<LinearLayout
android:id="@+id/deleteFrame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".1"
android:gravity="end"
android:visibility="gone">
<ImageView
android:id="@+id/deleteEmail"
android:layout_width="@dimen/dimen18dp"
android:layout_height="@dimen/dimen18dp"
android:layout_marginStart="@dimen/dimen4dp"
android:layout_marginEnd="@dimen/dimen2dp"
android:layout_marginTop="@dimen/dimen2dp"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_delete"
app:tint="?attr/iconsColor" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -371,6 +371,8 @@
<string name="emailErrorInUse">Email address is already in use</string> <string name="emailErrorInUse">Email address is already in use</string>
<string name="emailTypeText">Primary</string> <string name="emailTypeText">Primary</string>
<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="deleteEmailSuccess">Email deleted successfully</string>
<!-- account settings --> <!-- account settings -->
<!-- single issue section --> <!-- single issue section -->