diff options
author | Niedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com> | 2020-10-04 12:28:51 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-04 12:28:51 +0300 |
commit | a2967749b4bbf46501072df9442f7a5296ca9b31 (patch) | |
tree | 4b184c016e82784555a1a23cab26e70b559eea23 | |
parent | 180983642de284cf60266c6cedc0012bf1cf4a17 (diff) |
Assignee dialog (#693)
* New assignee dialog
Signed-off-by: Stefan Niedermann <info@niedermann.it>
* Fix color chooser
Signed-off-by: Stefan Niedermann <info@niedermann.it>
* Use BrandedDeleteAlertDialogBuilder instead of BrandedAlertDialogBuilder
Signed-off-by: Stefan Niedermann <info@niedermann.it>
7 files changed, 164 insertions, 18 deletions
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(); + } } diff --git a/app/src/main/res/layout/dialog_assignee.xml b/app/src/main/res/layout/dialog_assignee.xml new file mode 100644 index 000000000..c0f3e3218 --- /dev/null +++ b/app/src/main/res/layout/dialog_assignee.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <ImageView + android:id="@+id/avatar" + android:layout_width="match_parent" + android:layout_height="200dp" + android:contentDescription="@string/user_avatar" + android:scaleType="centerCrop" + android:src="@drawable/ic_person_grey600_24dp" /> + + <TextView + android:padding="?dialogPreferredPadding" + android:id="@+id/displayName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?attr/textAppearanceHeadline1" + tools:text="@tools:sample/full_names" /> +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1abd3ec4a..c1cedb708 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -312,4 +312,6 @@ <string name="cannot_upload_files_without_permission">Can not upload files without permission</string> <string name="clone_cards">Clone cards</string> <string name="simple_clone">Clone</string> + <string name="user_avatar">User avatar</string> + <string name="simple_unassign">Unassign</string> </resources> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index f0bff78fe..c253ae461 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -6,6 +6,7 @@ <item name="colorAccent">@color/accent</item> <item name="toolbarStyle">@style/toolbarStyle</item> <item name="android:windowBackground">?attr/colorPrimary</item> + <item name="textAppearanceHeadline1">@style/Deck.TextAppearance.Headline1</item> </style> <style name="toolbarStyle" parent="@style/Widget.AppCompat.Toolbar"> @@ -32,4 +33,8 @@ <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowIsTranslucent">true</item> </style> + + <style name="Deck.TextAppearance.Headline1" parent="TextAppearance.MaterialComponents.Headline1"> + <item name="android:textSize">36sp</item> + </style> </resources> |