From a2967749b4bbf46501072df9442f7a5296ca9b31 Mon Sep 17 00:00:00 2001 From: Niedermann IT-Dienstleistungen Date: Sun, 4 Oct 2020 11:28:51 +0200 Subject: Assignee dialog (#693) * New assignee dialog Signed-off-by: Stefan Niedermann * Fix color chooser Signed-off-by: Stefan Niedermann * Use BrandedDeleteAlertDialogBuilder instead of BrandedAlertDialogBuilder Signed-off-by: Stefan Niedermann --- .../it/niedermann/nextcloud/deck/model/User.java | 4 +- .../deck/ui/card/assignee/CardAssigneeDialog.java | 99 ++++++++++++++++++++++ .../ui/card/assignee/CardAssigneeListener.java | 11 +++ .../deck/ui/card/details/CardDetailsFragment.java | 38 +++++---- 4 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java create mode 100644 app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeListener.java (limited to 'app/src/main/java/it') diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/User.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/User.java index cfb48d543..fd318ce7a 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/model/User.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/User.java @@ -4,10 +4,12 @@ import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.Index; +import java.io.Serializable; + import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity; @Entity(inheritSuperIndices = true, indices = {@Index(value = "uid", name = "user_uid")}) -public class User extends AbstractRemoteEntity { +public class User extends AbstractRemoteEntity implements Serializable { private String primaryKey; diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java new file mode 100644 index 000000000..08f62165f --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java @@ -0,0 +1,99 @@ +package it.niedermann.nextcloud.deck.ui.card.assignee; + +import android.app.Dialog; +import android.content.Context; +import android.net.Uri; +import android.os.Bundle; +import android.view.LayoutInflater; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.lifecycle.ViewModelProvider; + +import com.bumptech.glide.Glide; + +import java.io.Serializable; + +import it.niedermann.nextcloud.deck.R; +import it.niedermann.nextcloud.deck.databinding.DialogAssigneeBinding; +import it.niedermann.nextcloud.deck.model.User; +import it.niedermann.nextcloud.deck.ui.branding.BrandedDeleteAlertDialogBuilder; +import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment; +import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel; + +public class CardAssigneeDialog extends BrandedDialogFragment { + + private static final String KEY_USER = "user"; + private DialogAssigneeBinding binding; + private EditCardViewModel viewModel; + + @Nullable + private CardAssigneeListener cardAssigneeListener = null; + @SuppressWarnings("NotNullFieldNotInitialized") + @NonNull + private User user; + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + + if (getParentFragment() instanceof CardAssigneeListener) { + this.cardAssigneeListener = (CardAssigneeListener) getParentFragment(); + } else if (context instanceof CardAssigneeListener) { + this.cardAssigneeListener = (CardAssigneeListener) context; + } + + final Bundle args = requireArguments(); + if (!args.containsKey(KEY_USER)) { + throw new IllegalArgumentException("Provide at least " + KEY_USER); + } + final Serializable user = args.getSerializable(KEY_USER); + if (user == null) { + throw new IllegalArgumentException(KEY_USER + " must not be null."); + } + this.user = (User) user; + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + binding = DialogAssigneeBinding.inflate(LayoutInflater.from(requireContext())); + viewModel = new ViewModelProvider(requireActivity()).get(EditCardViewModel.class); + + AlertDialog.Builder dialogBuilder = new BrandedDeleteAlertDialogBuilder(requireContext()); + + if (viewModel.canEdit() && cardAssigneeListener != null) { + dialogBuilder.setPositiveButton(R.string.simple_unassign, (d, w) -> cardAssigneeListener.onUnassignUser(user)); + } + + return dialogBuilder + .setView(binding.getRoot()) + .setNeutralButton(R.string.simple_close, null) + .create(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + binding.avatar.post(() -> Glide.with(binding.avatar.getContext()) + .load(viewModel.getAccount().getUrl() + "/index.php/avatar/" + Uri.encode(user.getUid()) + "/" + binding.avatar.getWidth()) + .placeholder(R.drawable.ic_person_grey600_24dp) + .error(R.drawable.ic_person_grey600_24dp) + .into(binding.avatar)); + binding.displayName.setText(user.getDisplayname()); + } + + @Override + public void applyBrand(int mainColor) { + } + + public static DialogFragment newInstance(@NonNull User user) { + final DialogFragment fragment = new CardAssigneeDialog(); + final Bundle args = new Bundle(); + args.putSerializable(KEY_USER, user); + fragment.setArguments(args); + return fragment; + } +} diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeListener.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeListener.java new file mode 100644 index 000000000..259a8b57c --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeListener.java @@ -0,0 +1,11 @@ +package it.niedermann.nextcloud.deck.ui.card.assignee; + +import androidx.annotation.NonNull; + +import it.niedermann.nextcloud.deck.model.User; + +public interface CardAssigneeListener { + + void onUnassignUser(@NonNull User user); + +} \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java index d8186ce4b..6443a132a 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java @@ -15,6 +15,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.Px; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.drawable.DrawableCompat; import androidx.fragment.app.Fragment; @@ -50,6 +51,8 @@ import it.niedermann.nextcloud.deck.ui.branding.BrandedTimePickerDialog; import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel; import it.niedermann.nextcloud.deck.ui.card.LabelAutoCompleteAdapter; import it.niedermann.nextcloud.deck.ui.card.UserAutoCompleteAdapter; +import it.niedermann.nextcloud.deck.ui.card.assignee.CardAssigneeDialog; +import it.niedermann.nextcloud.deck.ui.card.assignee.CardAssigneeListener; import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment; import it.niedermann.nextcloud.deck.util.ColorUtil; import it.niedermann.nextcloud.deck.util.MarkDownUtil; @@ -61,7 +64,7 @@ import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.Liv import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText; import static it.niedermann.nextcloud.deck.util.DimensionUtil.dpToPx; -public class CardDetailsFragment extends BrandedFragment implements OnDateSetListener, OnTimeSetListener { +public class CardDetailsFragment extends BrandedFragment implements OnDateSetListener, OnTimeSetListener, CardAssigneeListener { private FragmentCardEditTabDetailsBinding binding; private EditCardViewModel viewModel; @@ -307,7 +310,7 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis final Chip chip = new Chip(activity); chip.setText(label.getTitle()); if (viewModel.canEdit()) { - chip.setCloseIcon(getResources().getDrawable(R.drawable.ic_close_circle_grey600)); + chip.setCloseIcon(ContextCompat.getDrawable(requireContext(), R.drawable.ic_close_circle_grey600)); chip.setCloseIconVisible(true); chip.setOnCloseIconClickListener(v -> { binding.labelsGroup.removeView(chip); @@ -332,21 +335,7 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis } private void setupAssignees() { - adapter = new AssigneeAdapter((user) -> { - if (viewModel.canEdit()) { - viewModel.getFullCard().getAssignedUsers().remove(user); - adapter.removeUser(user); - ((UserAutoCompleteAdapter) binding.people.getAdapter()).include(user); - BrandedSnackbar.make( - requireView(), getString(R.string.unassigned_user, user.getDisplayname()), - Snackbar.LENGTH_LONG) - .setAction(R.string.simple_undo, v1 -> { - viewModel.getFullCard().getAssignedUsers().add(user); - ((UserAutoCompleteAdapter) binding.people.getAdapter()).exclude(user); - adapter.addUser(user); - }).show(); - } - }, viewModel.getAccount()); + adapter = new AssigneeAdapter((user) -> CardAssigneeDialog.newInstance(user).show(getChildFragmentManager(), CardAssigneeDialog.class.getSimpleName()), viewModel.getAccount()); binding.assignees.setAdapter(adapter); binding.assignees.post(() -> { @Px final int gutter = dpToPx(requireContext(), R.dimen.spacer_1x); @@ -426,4 +415,19 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis binding.projects.setVisibility(GONE); } } + + @Override + public void onUnassignUser(@NonNull User user) { + viewModel.getFullCard().getAssignedUsers().remove(user); + adapter.removeUser(user); + ((UserAutoCompleteAdapter) binding.people.getAdapter()).include(user); + BrandedSnackbar.make( + requireView(), getString(R.string.unassigned_user, user.getDisplayname()), + Snackbar.LENGTH_LONG) + .setAction(R.string.simple_undo, v1 -> { + viewModel.getFullCard().getAssignedUsers().add(user); + ((UserAutoCompleteAdapter) binding.people.getAdapter()).exclude(user); + adapter.addUser(user); + }).show(); + } } -- cgit v1.2.3