Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2020-04-21 18:35:55 +0300
committerNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2020-04-21 21:18:28 +0300
commit47f79909944ffd2e0fa8b47deeb4a62d21f4c1e4 (patch)
tree4132e17ace253aa54368f13526cae32bad97caaf /app/src/main/java/it/niedermann
parentb8a0a33cdbed5363b7552f78660a010cba567adb (diff)
Use ViewModel for EditActivity
This is capable of solving #270 (NullPointerException when saving new card after rotating the device)
Diffstat (limited to 'app/src/main/java/it/niedermann')
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardTabAdapter.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java145
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java102
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java221
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/util/DimensionUtil.java2
5 files changed, 242 insertions, 230 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardTabAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardTabAdapter.java
index 408e1123c..0c384837f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardTabAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardTabAdapter.java
@@ -40,7 +40,7 @@ public class CardTabAdapter extends FragmentStateAdapter {
public Fragment createFragment(int position) {
switch (position) {
case 0:
- return CardDetailsFragment.newInstance(accountId, localId, boardId, canEdit);
+ return CardDetailsFragment.newInstance();
case 1:
return CardAttachmentsFragment.newInstance(accountId, localId, boardId, canEdit);
case 2:
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java
index 1b4348c35..cbfd5047b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java
@@ -9,19 +9,14 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.WindowManager;
+import androidx.lifecycle.ViewModelProvider;
+
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
-import java.util.ArrayList;
-import java.util.Date;
-
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityEditBinding;
import it.niedermann.nextcloud.deck.model.Attachment;
-import it.niedermann.nextcloud.deck.model.Card;
-import it.niedermann.nextcloud.deck.model.Label;
-import it.niedermann.nextcloud.deck.model.User;
-import it.niedermann.nextcloud.deck.model.full.FullCard;
import it.niedermann.nextcloud.deck.model.ocs.Version;
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
@@ -30,7 +25,6 @@ import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.card.attachments.NewCardAttachmentHandler;
import it.niedermann.nextcloud.deck.ui.card.comments.CommentAddedListener;
import it.niedermann.nextcloud.deck.ui.card.comments.CommentDeletedListener;
-import it.niedermann.nextcloud.deck.ui.card.details.CardDetailsListener;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
import it.niedermann.nextcloud.deck.util.CardUtil;
@@ -41,11 +35,12 @@ import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.BUNDLE_KEY_LOCAL_
import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.BUNDLE_KEY_STACK_ID;
import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.NO_LOCAL_ID;
-public class EditActivity extends BrandedActivity implements CardDetailsListener, CommentAddedListener, CommentDeletedListener, NewCardAttachmentHandler {
+public class EditActivity extends BrandedActivity implements CommentAddedListener, CommentDeletedListener, NewCardAttachmentHandler {
private ActivityEditBinding binding;
private SyncManager syncManager;
- boolean hasCommentsAbility = false;
+
+ private EditCardViewModel viewModel;
private static final int[] tabTitles = new int[]{
R.string.card_edit_details,
@@ -73,18 +68,11 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
R.drawable.ic_activity_light_grey
};
- private FullCard originalCard;
- private FullCard fullCard;
-
private long accountId;
private long boardId;
private long stackId;
private long localId;
- private boolean pendingCreation = false;
- private boolean canEdit;
- private boolean createMode;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -96,7 +84,7 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
setSupportActionBar(binding.toolbar);
- Bundle args = getIntent().getExtras();
+ final Bundle args = getIntent().getExtras();
if (args == null || !args.containsKey(BUNDLE_KEY_ACCOUNT_ID) || !args.containsKey(BUNDLE_KEY_BOARD_ID)) {
throw new IllegalArgumentException("Provide at least " + BUNDLE_KEY_ACCOUNT_ID + " and " + BUNDLE_KEY_BOARD_ID + " so we know where to create this new card.");
@@ -106,8 +94,11 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
boardId = args.getLong(BUNDLE_KEY_BOARD_ID);
localId = args.getLong(BUNDLE_KEY_LOCAL_ID, NO_LOCAL_ID);
+ viewModel = new ViewModelProvider(this).get(EditCardViewModel.class);
+ syncManager = new SyncManager(this);
+
if (localId == NO_LOCAL_ID) {
- createMode = true;
+ viewModel.setCreateMode(true);
if (args.containsKey(BUNDLE_KEY_STACK_ID)) {
stackId = args.getLong(BUNDLE_KEY_STACK_ID);
} else {
@@ -115,28 +106,19 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
}
}
- syncManager = new SyncManager(this);
-
observeOnce(syncManager.getFullBoardById(accountId, boardId), EditActivity.this, (fullBoard -> {
- canEdit = fullBoard.getBoard().isPermissionEdit();
+ viewModel.setCanEdit(fullBoard.getBoard().isPermissionEdit());
invalidateOptionsMenu();
- if (createMode) {
- fullCard = new FullCard();
- originalCard = new FullCard();
- fullCard.setLabels(new ArrayList<>());
- fullCard.setAssignedUsers(new ArrayList<>());
- fullCard.setAttachments(new ArrayList<>());
- Card card = new Card();
- card.setStackId(stackId);
- fullCard.setCard(card);
+ if (viewModel.isCreateMode()) {
+ viewModel.initializeNewCard(accountId, boardId, stackId);
+
setupViewPager();
- setupTitle(createMode);
+ setupTitle(viewModel.isCreateMode());
} else {
observeOnce(syncManager.getCardByLocalId(accountId, localId), EditActivity.this, (next) -> {
- fullCard = next;
- originalCard = new FullCard(fullCard);
+ viewModel.initializeExistingCard(accountId, boardId, next);
setupViewPager();
- setupTitle(createMode);
+ setupTitle(viewModel.isCreateMode());
});
}
}));
@@ -144,7 +126,7 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- if (canEdit) {
+ if (viewModel.canEdit()) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.card_edit_menu, menu);
} else {
@@ -162,23 +144,24 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
}
private void saveAndFinish() {
- if (!pendingCreation) {
- pendingCreation = true;
- if (fullCard.getCard().getTitle() == null || fullCard.getCard().getTitle().isEmpty()) {
- fullCard.getCard().setTitle(CardUtil.generateTitleFromDescription(fullCard.getCard().getDescription()));
+ if (!viewModel.isPendingCreation()) {
+ viewModel.setPendingCreation(true);
+ final String title = viewModel.getFullCard().getCard().getTitle();
+ if (title == null || title.isEmpty()) {
+ viewModel.getFullCard().getCard().setTitle(CardUtil.generateTitleFromDescription(viewModel.getFullCard().getCard().getDescription()));
}
- if (fullCard.getCard().getTitle().isEmpty()) {
+ if (viewModel.getFullCard().getCard().getTitle().isEmpty()) {
new BrandedAlertDialogBuilder(this)
.setTitle(R.string.title_is_mandatory)
.setMessage(R.string.provide_at_least_a_title_or_description)
.setPositiveButton(android.R.string.ok, null)
- .setOnDismissListener(dialog -> pendingCreation = false)
+ .setOnDismissListener(dialog -> viewModel.setPendingCreation(false))
.show();
} else {
- if (createMode) {
- observeOnce(syncManager.createFullCard(accountId, boardId, stackId, fullCard), EditActivity.this, (card) -> super.finish());
+ if (viewModel.isCreateMode()) {
+ observeOnce(syncManager.createFullCard(accountId, boardId, stackId, viewModel.getFullCard()), EditActivity.this, (card) -> super.finish());
} else {
- observeOnce(syncManager.updateCard(fullCard), EditActivity.this, (card) -> super.finish());
+ observeOnce(syncManager.updateCard(viewModel.getFullCard()), EditActivity.this, (card) -> super.finish());
}
}
}
@@ -188,23 +171,21 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
binding.tabLayout.removeAllTabs();
binding.tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
- CardTabAdapter adapter = new CardTabAdapter(
+ final CardTabAdapter adapter = new CardTabAdapter(
getSupportFragmentManager(),
getLifecycle(),
accountId,
localId,
boardId,
- canEdit);
- TabLayoutMediator mediator = new TabLayoutMediator(binding.tabLayout, binding.pager, (tab, position) -> {
- tab.setIcon(
- hasCommentsAbility
- ? tabIconsWithComments[position]
- : tabIcons[position]
+ viewModel.canEdit());
+ final TabLayoutMediator mediator = new TabLayoutMediator(binding.tabLayout, binding.pager, (tab, position) -> {
+ tab.setIcon(viewModel.isHasCommentsAbility()
+ ? tabIconsWithComments[position]
+ : tabIcons[position]
);
- tab.setContentDescription(
- hasCommentsAbility
- ? tabTitlesWithComments[position]
- : tabTitles[position]
+ tab.setContentDescription(viewModel.isHasCommentsAbility()
+ ? tabTitlesWithComments[position]
+ : tabTitles[position]
);
});
runOnUiThread(() -> {
@@ -214,10 +195,10 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
});
// Comments API only available starting with version 1.0.0-alpha1
- if (!createMode) {
+ if (!viewModel.isCreateMode()) {
syncManager.readAccount(accountId).observe(this, (account) -> {
- hasCommentsAbility = ((account.getServerDeckVersionAsObject().compareTo(new Version("1.0.0", 1, 0, 0)) >= 0));
- if (hasCommentsAbility) {
+ viewModel.setHasCommentsAbility(account.getServerDeckVersionAsObject().isGreaterOrEqualTo(new Version("1.0.0", 1, 0, 0)));
+ if (viewModel.isHasCommentsAbility()) {
runOnUiThread(() -> {
mediator.detach();
adapter.enableComments();
@@ -230,20 +211,20 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
}
private void setupTitle(boolean createMode) {
- binding.title.setText(fullCard.getCard().getTitle());
- if (canEdit) {
+ binding.title.setText(viewModel.getFullCard().getCard().getTitle());
+ if (viewModel.canEdit()) {
if (createMode) {
binding.title.requestFocus();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
- if (fullCard.getCard().getTitle() != null) {
- binding.title.setSelection(fullCard.getCard().getTitle().length());
+ if (viewModel.getFullCard().getCard().getTitle() != null) {
+ binding.title.setSelection(viewModel.getFullCard().getCard().getTitle().length());
}
}
binding.title.setHint(getString(createMode ? R.string.simple_add : R.string.edit));
binding.title.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
- fullCard.getCard().setTitle(binding.title.getText().toString());
+ viewModel.getFullCard().getCard().setTitle(binding.title.getText().toString());
}
@Override
@@ -261,36 +242,6 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
}
@Override
- public void onDescriptionChanged(String description) {
- this.fullCard.getCard().setDescription(description);
- }
-
- @Override
- public void onUserAdded(User user) {
- this.fullCard.getAssignedUsers().add(user);
- }
-
- @Override
- public void onUserRemoved(User user) {
- this.fullCard.getAssignedUsers().remove(user);
- }
-
- @Override
- public void onLabelAdded(Label label) {
- this.fullCard.getLabels().add(label);
- }
-
- @Override
- public void onLabelRemoved(Label label) {
- this.fullCard.getLabels().remove(label);
- }
-
- @Override
- public void onDueDateChanged(Date dueDate) {
- this.fullCard.getCard().setDueDate(dueDate);
- }
-
- @Override
public boolean onSupportNavigateUp() {
finish(); // close this activity as oppose to navigating up
return true;
@@ -303,7 +254,7 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
@Override
public void finish() {
- if (!fullCard.equals(originalCard) && canEdit) {
+ if (!viewModel.hasChanges() && viewModel.canEdit()) {
new BrandedAlertDialogBuilder(this)
.setTitle(R.string.simple_save)
.setMessage(R.string.do_you_want_to_save_your_changes)
@@ -321,12 +272,12 @@ public class EditActivity extends BrandedActivity implements CardDetailsListener
@Override
public void attachmentAdded(Attachment attachment) {
- fullCard.getAttachments().add(attachment);
+ viewModel.getFullCard().getAttachments().add(attachment);
}
@Override
public void attachmentRemoved(Attachment attachment) {
- fullCard.getAttachments().remove(attachment);
+ viewModel.getFullCard().getAttachments().remove(attachment);
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java
new file mode 100644
index 000000000..f89a95a66
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java
@@ -0,0 +1,102 @@
+package it.niedermann.nextcloud.deck.ui.card;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.ViewModel;
+
+import java.util.ArrayList;
+
+import it.niedermann.nextcloud.deck.model.Card;
+import it.niedermann.nextcloud.deck.model.full.FullCard;
+
+@SuppressWarnings("WeakerAccess")
+public class EditCardViewModel extends ViewModel {
+
+ private long accountId;
+ private long boardId;
+ private FullCard originalCard;
+ private FullCard fullCard;
+ private boolean hasCommentsAbility = false;
+ private boolean pendingCreation = false;
+ private boolean canEdit = false;
+ private boolean createMode = false;
+
+ /**
+ * Stores a deep copy of the given fullCard to be able to compare the state at every time in #{@link EditCardViewModel#hasChanges()}
+ *
+ * @param accountId Expecting a positive long value
+ * @param boardId Local ID, expecting a positive long value
+ * @param fullCard The card that is currently edited
+ */
+ public void initializeExistingCard(long accountId, long boardId, @NonNull FullCard fullCard) {
+ this.accountId = accountId;
+ this.boardId = boardId;
+ this.fullCard = fullCard;
+ this.originalCard = new FullCard(this.fullCard);
+ }
+
+ /**
+ * Stores a deep copy of the given fullCard to be able to compare the state at every time in #{@link EditCardViewModel#hasChanges()}
+ *
+ * @param accountId Expecting a positive long value
+ * @param boardId Local ID, expecting a positive long value
+ * @param stackId Local ID, expecting a positive long value where the card should be created
+ */
+ public void initializeNewCard(long accountId, long boardId, long stackId) {
+ final FullCard fullCard = new FullCard();
+ fullCard.setLabels(new ArrayList<>());
+ fullCard.setAssignedUsers(new ArrayList<>());
+ fullCard.setAttachments(new ArrayList<>());
+ final Card card = new Card();
+ card.setStackId(stackId);
+ fullCard.setCard(card);
+ initializeExistingCard(accountId, boardId, fullCard);
+ }
+
+ public boolean hasChanges() {
+ return fullCard.equals(originalCard);
+ }
+
+ public boolean isHasCommentsAbility() {
+ return hasCommentsAbility;
+ }
+
+ public void setHasCommentsAbility(boolean hasCommentsAbility) {
+ this.hasCommentsAbility = hasCommentsAbility;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public FullCard getFullCard() {
+ return fullCard;
+ }
+
+ public boolean isPendingCreation() {
+ return pendingCreation;
+ }
+
+ public void setPendingCreation(boolean pendingCreation) {
+ this.pendingCreation = pendingCreation;
+ }
+
+ public boolean canEdit() {
+ return canEdit;
+ }
+
+ public void setCanEdit(boolean canEdit) {
+ this.canEdit = canEdit;
+ }
+
+ public boolean isCreateMode() {
+ return createMode;
+ }
+
+ public void setCreateMode(boolean createMode) {
+ this.createMode = createMode;
+ }
+
+ public long getBoardId() {
+ return boardId;
+ }
+}
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 81efacba8..adb8e15e3 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,9 +15,12 @@ import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.chip.Chip;
import com.google.android.material.snackbar.Snackbar;
@@ -39,55 +42,40 @@ import java.util.Locale;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabDetailsBinding;
-import it.niedermann.nextcloud.deck.model.Card;
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.User;
-import it.niedermann.nextcloud.deck.model.full.FullCard;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDatePickerDialog;
import it.niedermann.nextcloud.deck.ui.branding.BrandedFragment;
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.util.ColorUtil;
-import it.niedermann.nextcloud.deck.util.DimensionUtil;
import it.niedermann.nextcloud.deck.util.MarkDownUtil;
import it.niedermann.nextcloud.deck.util.ViewUtil;
+import static android.text.format.DateFormat.getDateFormat;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToEditText;
-import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.BUNDLE_KEY_ACCOUNT_ID;
-import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.BUNDLE_KEY_BOARD_ID;
-import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.BUNDLE_KEY_CAN_EDIT;
-import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.BUNDLE_KEY_LOCAL_ID;
-import static it.niedermann.nextcloud.deck.ui.card.CardAdapter.NO_LOCAL_ID;
+import static it.niedermann.nextcloud.deck.util.DimensionUtil.dpToPx;
public class CardDetailsFragment extends BrandedFragment implements OnDateSetListener, OnTimeSetListener {
private FragmentCardEditTabDetailsBinding binding;
-
- private boolean canEdit = false;
- private FullCard fullCard;
+ private EditCardViewModel viewModel;
private SyncManager syncManager;
private DateFormat dateFormat;
private DateFormat dueTime = new SimpleDateFormat("HH:mm", Locale.ROOT);
private String baseUrl;
+ @Px
private int avatarSize;
private LinearLayout.LayoutParams avatarLayoutParams;
- private CardDetailsListener cardDetailsListener;
private AppCompatActivity activity;
- public CardDetailsFragment() {
- }
-
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
- if (context instanceof CardDetailsListener) {
- this.cardDetailsListener = (CardDetailsListener) context;
- } else {
- throw new ClassCastException("Caller must implement " + CardDetailsListener.class.getCanonicalName());
- }
if (context instanceof AppCompatActivity) {
this.activity = (AppCompatActivity) context;
} else {
@@ -95,17 +83,8 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
}
}
- public static CardDetailsFragment newInstance(long accountId, long localId, long boardId, boolean canEdit) {
- Bundle bundle = new Bundle();
- bundle.putLong(BUNDLE_KEY_ACCOUNT_ID, accountId);
- bundle.putLong(BUNDLE_KEY_BOARD_ID, boardId);
- bundle.putLong(BUNDLE_KEY_LOCAL_ID, localId);
- bundle.putBoolean(BUNDLE_KEY_CAN_EDIT, canEdit);
-
- CardDetailsFragment fragment = new CardDetailsFragment();
- fragment.setArguments(bundle);
-
- return fragment;
+ public static Fragment newInstance() {
+ return new CardDetailsFragment();
}
@Override
@@ -113,53 +92,58 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCardEditTabDetailsBinding.inflate(inflater, container, false);
- dateFormat = android.text.format.DateFormat.getDateFormat(activity);
-
- Bundle args = getArguments();
- if (args != null) {
- long accountId = args.getLong(BUNDLE_KEY_ACCOUNT_ID);
- long localId = args.getLong(BUNDLE_KEY_LOCAL_ID);
- long boardId = args.getLong(BUNDLE_KEY_BOARD_ID);
- if (args.containsKey(BUNDLE_KEY_CAN_EDIT)) {
- this.canEdit = args.getBoolean(BUNDLE_KEY_CAN_EDIT);
- }
+ dateFormat = getDateFormat(activity);
- syncManager = new SyncManager(activity);
-
- if (NO_LOCAL_ID.equals(localId)) {
- fullCard = new FullCard();
- fullCard.setCard(new Card());
- setupView(accountId, boardId, canEdit);
- } else {
- observeOnce(syncManager.getCardByLocalId(accountId, localId), CardDetailsFragment.this, (next) -> {
- fullCard = next;
- binding.description.setText(fullCard.getCard().getDescription());
- setupView(accountId, boardId, canEdit);
- });
- }
- }
+ viewModel = new ViewModelProvider(activity).get(EditCardViewModel.class);
+ syncManager = new SyncManager(activity);
- avatarSize = DimensionUtil.dpToPx(requireContext(), R.dimen.avatar_size);
+ avatarSize = dpToPx(requireContext(), R.dimen.avatar_size);
avatarLayoutParams = new LinearLayout.LayoutParams(avatarSize, avatarSize);
- avatarLayoutParams.setMargins(0, 0, requireContext().getResources().getDimensionPixelSize(R.dimen.spacer_1x), 0);
+ avatarLayoutParams.setMargins(0, 0, dpToPx(requireContext(), R.dimen.spacer_1x), 0);
try {
baseUrl = syncManager.getServerUrl();
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
DeckLog.logError(e);
}
- return binding.getRoot();
- }
- private void setupView(long accountId, long boardId, boolean canEdit) {
- setupPeople(accountId, boardId);
- setupLabels(accountId, boardId, canEdit);
+ setupPeople();
+ setupLabels();
setupDueDate();
setupDescription();
+ binding.description.setText(viewModel.getFullCard().getCard().getDescription());
+
+ return binding.getRoot();
+ }
+
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // https://github.com/wdullaer/MaterialDateTimePicker#why-are-my-callbacks-lost-when-the-device-changes-orientation
+ final DatePickerDialog dpd = (DatePickerDialog) getChildFragmentManager().findFragmentByTag(BrandedDatePickerDialog.class.getCanonicalName());
+ final TimePickerDialog tpd = (TimePickerDialog) getChildFragmentManager().findFragmentByTag(BrandedTimePickerDialog.class.getCanonicalName());
+ if (tpd != null) tpd.setOnTimeSetListener(this);
+ if (dpd != null) dpd.setOnDateSetListener(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ applyBrandToEditText(mainColor, textColor, binding.labels);
+ applyBrandToEditText(mainColor, textColor, binding.dueDateDate);
+ applyBrandToEditText(mainColor, textColor, binding.dueDateTime);
+ applyBrandToEditText(mainColor, textColor, binding.people);
+ applyBrandToEditText(mainColor, textColor, binding.description);
}
private void setupDescription() {
- if (canEdit) {
+ if (viewModel.canEdit()) {
MarkdownProcessor markdownProcessor = new MarkdownProcessor(requireContext());
markdownProcessor.config(MarkDownUtil.getMarkDownConfiguration(binding.description.getContext()).build());
markdownProcessor.factory(EditFactory.create());
@@ -167,9 +151,8 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
binding.description.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
- if (fullCard != null) {
- cardDetailsListener.onDescriptionChanged(binding.description.getText().toString());
- fullCard.getCard().setDescription(binding.description.getText().toString());
+ if (viewModel.getFullCard() != null) {
+ viewModel.getFullCard().getCard().setDescription(binding.description.getText().toString());
}
}
@@ -225,9 +208,9 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
}
private void setupDueDate() {
- if (this.fullCard.getCard().getDueDate() != null) {
- binding.dueDateDate.setText(dateFormat.format(this.fullCard.getCard().getDueDate()));
- binding.dueDateTime.setText(dueTime.format(this.fullCard.getCard().getDueDate()));
+ if (this.viewModel.getFullCard().getCard().getDueDate() != null) {
+ binding.dueDateDate.setText(dateFormat.format(this.viewModel.getFullCard().getCard().getDueDate()));
+ binding.dueDateTime.setText(dueTime.format(this.viewModel.getFullCard().getCard().getDueDate()));
binding.clearDueDate.setVisibility(View.VISIBLE);
} else {
binding.clearDueDate.setVisibility(View.GONE);
@@ -235,29 +218,28 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
binding.dueDateTime.setText(null);
}
- if (canEdit) {
+ if (viewModel.canEdit()) {
binding.dueDateDate.setOnClickListener(v -> {
- if (fullCard != null && fullCard.getCard() != null) {
- createDatePickerDialogFromDate(this, fullCard.getCard().getDueDate()).show(getChildFragmentManager(), BrandedDatePickerDialog.class.getCanonicalName());
+ if (viewModel.getFullCard() != null && viewModel.getFullCard().getCard() != null) {
+ createDatePickerDialogFromDate(this, viewModel.getFullCard().getCard().getDueDate()).show(getChildFragmentManager(), BrandedDatePickerDialog.class.getCanonicalName());
} else {
createDatePickerDialogFromDate(this, null).show(getChildFragmentManager(), BrandedDatePickerDialog.class.getCanonicalName());
}
});
binding.dueDateTime.setOnClickListener(v -> {
- if (fullCard != null && fullCard.getCard() != null) {
- createTimePickerDialogFromDate(this, fullCard.getCard().getDueDate()).show(getChildFragmentManager(), BrandedTimePickerDialog.class.getCanonicalName());
+ if (viewModel.getFullCard() != null && viewModel.getFullCard().getCard() != null) {
+ createTimePickerDialogFromDate(this, viewModel.getFullCard().getCard().getDueDate()).show(getChildFragmentManager(), BrandedTimePickerDialog.class.getCanonicalName());
} else {
createTimePickerDialogFromDate(this, null).show(getChildFragmentManager(), BrandedTimePickerDialog.class.getCanonicalName());
}
});
binding.clearDueDate.setOnClickListener(v -> {
- cardDetailsListener.onDueDateChanged(null);
binding.dueDateDate.setText(null);
binding.dueDateTime.setText(null);
- fullCard.getCard().setDueDate(null);
+ viewModel.getFullCard().getCard().setDueDate(null);
binding.clearDueDate.setVisibility(View.GONE);
});
} else {
@@ -267,10 +249,12 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
}
}
- private void setupLabels(long accountId, long boardId, boolean canEdit) {
+ private void setupLabels() {
+ long accountId = viewModel.getAccountId();
+ long boardId = viewModel.getBoardId();
binding.labelsGroup.removeAllViews();
- if (canEdit) {
- Long localCardId = fullCard.getCard().getLocalId();
+ if (viewModel.canEdit()) {
+ Long localCardId = viewModel.getFullCard().getCard().getLocalId();
localCardId = localCardId == null ? -1 : localCardId;
binding.labels.setAdapter(new LabelAutoCompleteAdapter(activity, accountId, boardId, localCardId));
binding.labels.setOnItemClickListener((adapterView, view, position, id) -> {
@@ -283,13 +267,13 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
observeOnce(syncManager.createLabel(accountId, newLabel, boardId), CardDetailsFragment.this, createdLabel -> {
newLabel.setLocalId(createdLabel.getLocalId());
((LabelAutoCompleteAdapter) binding.labels.getAdapter()).exclude(createdLabel);
- cardDetailsListener.onLabelAdded(createdLabel);
+ viewModel.getFullCard().getLabels().add(createdLabel);
binding.labelsGroup.addView(createChipFromLabel(newLabel));
binding.labelsGroup.setVisibility(View.VISIBLE);
});
} else {
((LabelAutoCompleteAdapter) binding.labels.getAdapter()).exclude(label);
- cardDetailsListener.onLabelAdded(label);
+ viewModel.getFullCard().getLabels().add(label);
binding.labelsGroup.addView(createChipFromLabel(label));
binding.labelsGroup.setVisibility(View.VISIBLE);
}
@@ -299,8 +283,8 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
} else {
binding.labels.setEnabled(false);
}
- if (fullCard.getLabels() != null && fullCard.getLabels().size() > 0) {
- for (Label label : fullCard.getLabels()) {
+ if (viewModel.getFullCard().getLabels() != null && viewModel.getFullCard().getLabels().size() > 0) {
+ for (Label label : viewModel.getFullCard().getLabels()) {
binding.labelsGroup.addView(createChipFromLabel(label));
}
binding.labelsGroup.setVisibility(View.VISIBLE);
@@ -313,12 +297,12 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
private Chip createChipFromLabel(Label label) {
final Chip chip = new Chip(activity);
chip.setText(label.getTitle());
- if (canEdit) {
+ if (viewModel.canEdit()) {
chip.setCloseIcon(getResources().getDrawable(R.drawable.ic_close_circle_grey600));
chip.setCloseIconVisible(true);
chip.setOnCloseIconClickListener(v -> {
binding.labelsGroup.removeView(chip);
- cardDetailsListener.onLabelRemoved(label);
+ viewModel.getFullCard().getLabels().remove(label);
((LabelAutoCompleteAdapter) binding.labels.getAdapter()).exclude(label);
});
}
@@ -338,14 +322,14 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
return chip;
}
- private void setupPeople(long accountId, long boardId) {
- if (canEdit) {
- Long localCardId = fullCard.getCard().getLocalId();
+ private void setupPeople() {
+ if (viewModel.canEdit()) {
+ Long localCardId = viewModel.getFullCard().getCard().getLocalId();
localCardId = localCardId == null ? -1 : localCardId;
- binding.people.setAdapter(new UserAutoCompleteAdapter(activity, accountId, boardId, localCardId));
+ binding.people.setAdapter(new UserAutoCompleteAdapter(activity, viewModel.getAccountId(), viewModel.getBoardId(), localCardId));
binding.people.setOnItemClickListener((adapterView, view, position, id) -> {
User user = (User) adapterView.getItemAtPosition(position);
- cardDetailsListener.onUserAdded(user);
+ viewModel.getFullCard().getAssignedUsers().add(user);
((UserAutoCompleteAdapter) binding.people.getAdapter()).exclude(user);
if (baseUrl != null) {
addAvatar(baseUrl, user);
@@ -353,10 +337,10 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
binding.people.setText("");
});
- if (this.fullCard.getAssignedUsers() != null) {
+ if (this.viewModel.getFullCard().getAssignedUsers() != null) {
binding.peopleList.removeAllViews();
if (baseUrl != null) {
- for (User user : this.fullCard.getAssignedUsers()) {
+ for (User user : this.viewModel.getFullCard().getAssignedUsers()) {
addAvatar(baseUrl, user);
}
}
@@ -369,16 +353,16 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
private void addAvatar(String baseUrl, User user) {
ImageView avatar = new ImageView(activity);
avatar.setLayoutParams(avatarLayoutParams);
- if (canEdit) {
+ if (viewModel.canEdit()) {
avatar.setOnClickListener(v -> {
- cardDetailsListener.onUserRemoved(user);
+ viewModel.getFullCard().getAssignedUsers().remove(user);
binding.peopleList.removeView(avatar);
((UserAutoCompleteAdapter) binding.people.getAdapter()).include(user);
Snackbar.make(
requireView(), getString(R.string.unassigned_user, user.getDisplayname()),
Snackbar.LENGTH_LONG)
.setAction(R.string.simple_undo, v1 -> {
- cardDetailsListener.onUserAdded(user);
+ viewModel.getFullCard().getAssignedUsers().add(user);
((UserAutoCompleteAdapter) binding.people.getAdapter()).exclude(user);
addAvatar(baseUrl, user);
}).show();
@@ -390,50 +374,24 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
}
@Override
- public void onResume() {
- super.onResume();
-
- // https://github.com/wdullaer/MaterialDateTimePicker#why-are-my-callbacks-lost-when-the-device-changes-orientation
- final DatePickerDialog dpd = (DatePickerDialog) getChildFragmentManager().findFragmentByTag(BrandedDatePickerDialog.class.getCanonicalName());
- final TimePickerDialog tpd = (TimePickerDialog) getChildFragmentManager().findFragmentByTag(BrandedTimePickerDialog.class.getCanonicalName());
- if (tpd != null) tpd.setOnTimeSetListener(this);
- if (dpd != null) dpd.setOnDateSetListener(this);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- }
-
- @Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToEditText(mainColor, textColor, binding.labels);
- applyBrandToEditText(mainColor, textColor, binding.dueDateDate);
- applyBrandToEditText(mainColor, textColor, binding.dueDateTime);
- applyBrandToEditText(mainColor, textColor, binding.people);
- applyBrandToEditText(mainColor, textColor, binding.description);
- }
-
- @Override
public void onDateSet(com.wdullaer.materialdatetimepicker.date.DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
Calendar c = Calendar.getInstance();
int hourOfDay;
int minute;
if (binding.dueDateTime.getText() != null && binding.dueDateTime.length() > 0) {
- hourOfDay = this.fullCard.getCard().getDueDate().getHours();
- minute = this.fullCard.getCard().getDueDate().getMinutes();
+ hourOfDay = this.viewModel.getFullCard().getCard().getDueDate().getHours();
+ minute = this.viewModel.getFullCard().getCard().getDueDate().getMinutes();
} else {
hourOfDay = 0;
minute = 0;
}
c.set(year, monthOfYear, dayOfMonth, hourOfDay, minute);
- this.fullCard.getCard().setDueDate(c.getTime());
+ this.viewModel.getFullCard().getCard().setDueDate(c.getTime());
binding.dueDateDate.setText(dateFormat.format(c.getTime()));
- cardDetailsListener.onDueDateChanged(fullCard.card.getDueDate());
- if (this.fullCard.getCard().getDueDate() == null || this.fullCard.getCard().getDueDate().getTime() == 0) {
+ if (this.viewModel.getFullCard().getCard().getDueDate() == null || this.viewModel.getFullCard().getCard().getDueDate().getTime() == 0) {
binding.clearDueDate.setVisibility(View.GONE);
} else {
binding.clearDueDate.setVisibility(View.VISIBLE);
@@ -442,14 +400,13 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
@Override
public void onTimeSet(com.wdullaer.materialdatetimepicker.time.TimePickerDialog view, int hourOfDay, int minute, int second) {
- if (this.fullCard.getCard().getDueDate() == null) {
- this.fullCard.getCard().setDueDate(new Date());
+ if (this.viewModel.getFullCard().getCard().getDueDate() == null) {
+ this.viewModel.getFullCard().getCard().setDueDate(new Date());
}
- this.fullCard.getCard().getDueDate().setHours(hourOfDay);
- this.fullCard.getCard().getDueDate().setMinutes(minute);
- binding.dueDateTime.setText(dueTime.format(this.fullCard.getCard().getDueDate().getTime()));
- cardDetailsListener.onDueDateChanged(fullCard.card.getDueDate());
- if (this.fullCard.getCard().getDueDate() == null || this.fullCard.getCard().getDueDate().getTime() == 0) {
+ this.viewModel.getFullCard().getCard().getDueDate().setHours(hourOfDay);
+ this.viewModel.getFullCard().getCard().getDueDate().setMinutes(minute);
+ binding.dueDateTime.setText(dueTime.format(this.viewModel.getFullCard().getCard().getDueDate().getTime()));
+ if (this.viewModel.getFullCard().getCard().getDueDate() == null || this.viewModel.getFullCard().getCard().getDueDate().getTime() == 0) {
binding.clearDueDate.setVisibility(View.GONE);
} else {
binding.clearDueDate.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/DimensionUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/DimensionUtil.java
index 19c01a06f..6ff22eace 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/util/DimensionUtil.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/DimensionUtil.java
@@ -4,11 +4,13 @@ import android.content.Context;
import androidx.annotation.DimenRes;
import androidx.annotation.NonNull;
+import androidx.annotation.Px;
public final class DimensionUtil {
private DimensionUtil() {
}
+ @Px
public static int dpToPx(@NonNull Context context, @DimenRes int resource) {
return context.getResources().getDimensionPixelSize(resource);
}