#831 Migrate from SQLiteOpenHelper to Room

Refactor selected navigation category
This commit is contained in:
Stefan Niedermann 2020-10-09 09:19:20 +02:00
parent 149d78b984
commit b40e62a2c1
11 changed files with 233 additions and 144 deletions

View file

@ -30,7 +30,7 @@ import it.niedermann.owncloud.notes.main.NavigationAdapter;
import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.Note;
import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.model.Capabilities;
import it.niedermann.owncloud.notes.shared.model.OldCategory; import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.DBStatus;
import it.niedermann.owncloud.notes.shared.util.NoteUtil; import it.niedermann.owncloud.notes.shared.util.NoteUtil;
@ -583,12 +583,12 @@ public class NotesNotesDatabaseTest {
long noteID = db.addNote(account.getId(), cloudNote); long noteID = db.addNote(account.getId(), cloudNote);
// check the default value of ordering_method // check the default value of ordering_method
CategorySortingMethod defaultMethod = db.getCategoryDao().getCategoryOrderByTitle(account.getId(), "CodingDiary"); CategorySortingMethod defaultMethod = db.getCategoryDao().getCategoryOrder(account.getId(), "CodingDiary");
assertEquals(defaultMethod, CategorySortingMethod.getCSM(0)); assertEquals(defaultMethod, CategorySortingMethod.getCSM(0));
// modify the value of ordering_method and check // modify the value of ordering_method and check
db.getCategoryDao().modifyCategoryOrderByTitle(account.getId(), "CodingDiary", CategorySortingMethod.getCSM(1)); db.getCategoryDao().modifyCategoryOrder(account.getId(), "CodingDiary", CategorySortingMethod.getCSM(1));
CategorySortingMethod methodAfterModify = db.getCategoryDao().getCategoryOrderByTitle(account.getId(), "CodingDiary"); CategorySortingMethod methodAfterModify = db.getCategoryDao().getCategoryOrder(account.getId(), "CodingDiary");
assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1)); assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1));
// delete the Node // delete the Node
@ -606,12 +606,12 @@ public class NotesNotesDatabaseTest {
long noteID = db.addNote(account.getId(), cloudNote); long noteID = db.addNote(account.getId(), cloudNote);
// check the default value of ordering_method // check the default value of ordering_method
CategorySortingMethod defaultMethod = db.getCategoryOrder(account.getId(), new OldCategory("CodingDiary", false)); CategorySortingMethod defaultMethod = db.getCategoryOrder(account.getId(), new NavigationCategory(type, "CodingDiary", false));
assertEquals(defaultMethod, CategorySortingMethod.getCSM(0)); assertEquals(defaultMethod, CategorySortingMethod.getCSM(0));
// modify the value of ordering_method and check // modify the value of ordering_method and check
db.getCategoryDao().modifyCategoryOrderByTitle(account.getId(), "CodingDiary", CategorySortingMethod.getCSM(1)); db.getCategoryDao().modifyCategoryOrder(account.getId(), "CodingDiary", CategorySortingMethod.getCSM(1));
CategorySortingMethod methodAfterModify = db.getCategoryOrder(account.getId(), new OldCategory("CodingDiary", false)); CategorySortingMethod methodAfterModify = db.getCategoryOrder(account.getId(), new NavigationCategory(type, "CodingDiary", false));
assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1)); assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1));
// delete the Node // delete the Node
@ -625,31 +625,31 @@ public class NotesNotesDatabaseTest {
spe.apply(); spe.apply();
// check default value // check default value
// all notes // all notes
defaultMethod = db.getCategoryOrder(account.getId(), new OldCategory(null, false)); defaultMethod = db.getCategoryOrder(account.getId(), new NavigationCategory(type, null, false));
assertEquals(defaultMethod, CategorySortingMethod.getCSM(0)); assertEquals(defaultMethod, CategorySortingMethod.getCSM(0));
// uncategorized // uncategorized
defaultMethod = db.getCategoryOrder(account.getId(), new OldCategory("", false)); defaultMethod = db.getCategoryOrder(account.getId(), new NavigationCategory(type, "", false));
assertEquals(defaultMethod, CategorySortingMethod.getCSM(0)); assertEquals(defaultMethod, CategorySortingMethod.getCSM(0));
// favorite // favorite
defaultMethod = db.getCategoryOrder(account.getId(), new OldCategory(null, true)); defaultMethod = db.getCategoryOrder(account.getId(), new NavigationCategory(type, null, true));
assertEquals(defaultMethod, CategorySortingMethod.getCSM(0)); assertEquals(defaultMethod, CategorySortingMethod.getCSM(0));
// modify the value of ordering_method and check // modify the value of ordering_method and check
// all notes // all notes
db.modifyCategoryOrder(account.getId(), new OldCategory(null, false), CategorySortingMethod.getCSM(1)); db.modifyCategoryOrder(account.getId(), new NavigationCategory(type, null, false), CategorySortingMethod.getCSM(1));
methodAfterModify = db.getCategoryOrder(account.getId(), new OldCategory(null, false)); methodAfterModify = db.getCategoryOrder(account.getId(), new NavigationCategory(type, null, false));
assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1)); assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1));
// uncategorized // uncategorized
db.modifyCategoryOrder(account.getId(), new OldCategory("", false), CategorySortingMethod.getCSM(1)); db.modifyCategoryOrder(account.getId(), new NavigationCategory(type, "", false), CategorySortingMethod.getCSM(1));
methodAfterModify = db.getCategoryOrder(account.getId(), new OldCategory("", false)); methodAfterModify = db.getCategoryOrder(account.getId(), new NavigationCategory(type, "", false));
assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1)); assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1));
// favorite // favorite
db.modifyCategoryOrder(account.getId(), new OldCategory(null, true), CategorySortingMethod.getCSM(1)); db.modifyCategoryOrder(account.getId(), new NavigationCategory(type, null, true), CategorySortingMethod.getCSM(1));
methodAfterModify = db.getCategoryOrder(account.getId(), new OldCategory(null, true)); methodAfterModify = db.getCategoryOrder(account.getId(), new NavigationCategory(type, null, true));
assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1)); assertEquals(methodAfterModify, CategorySortingMethod.getCSM(1));
// delete SharedPreferences // delete SharedPreferences

View file

@ -24,10 +24,14 @@ import it.niedermann.owncloud.notes.accountpicker.AccountPickerListener;
import it.niedermann.owncloud.notes.databinding.ActivityEditBinding; import it.niedermann.owncloud.notes.databinding.ActivityEditBinding;
import it.niedermann.owncloud.notes.main.MainActivity; import it.niedermann.owncloud.notes.main.MainActivity;
import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.Category;
import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.Note;
import it.niedermann.owncloud.notes.shared.model.OldCategory; import it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType;
import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import it.niedermann.owncloud.notes.shared.util.NoteUtil; import it.niedermann.owncloud.notes.shared.util.NoteUtil;
import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.FAVORITES;
public class EditNoteActivity extends LockedActivity implements BaseNoteFragment.NoteFragmentListener, AccountPickerListener { public class EditNoteActivity extends LockedActivity implements BaseNoteFragment.NoteFragmentListener, AccountPickerListener {
private static final String TAG = EditNoteActivity.class.getSimpleName(); private static final String TAG = EditNoteActivity.class.getSimpleName();
@ -156,12 +160,13 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment
private void launchNewNote() { private void launchNewNote() {
Intent intent = getIntent(); Intent intent = getIntent();
String category = null; String categoryTitle = null;
boolean favorite = false; boolean favorite = false;
if (intent.hasExtra(PARAM_CATEGORY)) { if (intent.hasExtra(PARAM_CATEGORY)) {
OldCategory categoryPreselection = (OldCategory) Objects.requireNonNull(intent.getSerializableExtra(PARAM_CATEGORY)); NavigationCategory categoryPreselection = (NavigationCategory) Objects.requireNonNull(intent.getSerializableExtra(PARAM_CATEGORY));
category = categoryPreselection.category; Category category = categoryPreselection.getCategory();
favorite = categoryPreselection.favorite != null ? categoryPreselection.favorite : false; categoryTitle = category == null ? "" : category.getTitle();
favorite = categoryPreselection.getType() == FAVORITES;
} }
String content = ""; String content = "";
@ -179,7 +184,7 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment
if (content == null) { if (content == null) {
content = ""; content = "";
} }
Note newNote = new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, favorite, category, null); Note newNote = new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, favorite, categoryTitle, null);
fragment = NoteEditFragment.newInstanceWithNewNote(newNote); fragment = NoteEditFragment.newInstanceWithNewNote(newNote);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_view, fragment).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_view, fragment).commit();
} }

View file

@ -77,6 +77,7 @@ import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider; import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.persistence.NotesDatabase;
import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.Category;
import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.Note;
import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory;
import it.niedermann.owncloud.notes.preferences.PreferencesActivity; import it.niedermann.owncloud.notes.preferences.PreferencesActivity;
@ -84,8 +85,8 @@ import it.niedermann.owncloud.notes.shared.model.Capabilities;
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.model.ISyncCallback;
import it.niedermann.owncloud.notes.shared.model.Item; import it.niedermann.owncloud.notes.shared.model.Item;
import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import it.niedermann.owncloud.notes.shared.model.NoteClickListener; import it.niedermann.owncloud.notes.shared.model.NoteClickListener;
import it.niedermann.owncloud.notes.shared.model.OldCategory;
import it.niedermann.owncloud.notes.shared.util.NoteUtil; import it.niedermann.owncloud.notes.shared.util.NoteUtil;
import static android.view.View.GONE; import static android.view.View.GONE;
@ -93,6 +94,10 @@ import static android.view.View.VISIBLE;
import static it.niedermann.owncloud.notes.NotesApplication.isDarkThemeActive; import static it.niedermann.owncloud.notes.NotesApplication.isDarkThemeActive;
import static it.niedermann.owncloud.notes.NotesApplication.isGridViewEnabled; import static it.niedermann.owncloud.notes.NotesApplication.isGridViewEnabled;
import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.DEFAULT_CATEGORY;
import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.FAVORITES;
import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.RECENT;
import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.UNCATEGORIZED;
import static it.niedermann.owncloud.notes.shared.util.ColorUtil.contrastRatioIsSufficient; import static it.niedermann.owncloud.notes.shared.util.ColorUtil.contrastRatioIsSufficient;
import static it.niedermann.owncloud.notes.shared.util.DisplayUtils.convertToCategoryNavigationItem; import static it.niedermann.owncloud.notes.shared.util.DisplayUtils.convertToCategoryNavigationItem;
import static it.niedermann.owncloud.notes.shared.util.SSOUtil.askForNewAccount; import static it.niedermann.owncloud.notes.shared.util.SSOUtil.askForNewAccount;
@ -147,7 +152,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
private NavigationItem itemFavorites; private NavigationItem itemFavorites;
private NavigationItem itemUncategorized; private NavigationItem itemUncategorized;
@NonNull @NonNull
private OldCategory navigationSelection = new OldCategory(null, null); private NavigationCategory navigationSelection = new NavigationCategory(RECENT);
private String navigationOpen = ""; private String navigationOpen = "";
boolean canMoveNoteToAnotherAccounts = false; boolean canMoveNoteToAnotherAccounts = false;
private ActionMode mActionMode; private ActionMode mActionMode;
@ -189,23 +194,32 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
this.fabCreate = binding.activityNotesListView.fabCreate; this.fabCreate = binding.activityNotesListView.fabCreate;
this.listView = binding.activityNotesListView.recyclerView; this.listView = binding.activityNotesListView.recyclerView;
mainViewModel.getSelectedCategory().observe(this, (category) -> { mainViewModel.getSelectedCategory().observe(this, (selectedCategory) -> {
View emptyContentView = binding.activityNotesListView.emptyContentView.getRoot(); View emptyContentView = binding.activityNotesListView.emptyContentView.getRoot();
emptyContentView.setVisibility(GONE); emptyContentView.setVisibility(GONE);
binding.activityNotesListView.progressCircular.setVisibility(VISIBLE); binding.activityNotesListView.progressCircular.setVisibility(VISIBLE);
this.navigationSelection = category; this.navigationSelection = selectedCategory;
fabCreate.show(); fabCreate.show();
String subtitle; String subtitle;
if (navigationSelection.category != null) { switch (navigationSelection.getType()) {
if (navigationSelection.category.isEmpty()) { case FAVORITES: {
subtitle = getString(R.string.search_in_category, getString(R.string.action_uncategorized)); subtitle = getString(R.string.search_in_category, getString(R.string.label_favorites));
} else { break;
subtitle = getString(R.string.search_in_category, NoteUtil.extendCategory(navigationSelection.category)); }
case UNCATEGORIZED: {
subtitle = getString(R.string.search_in_category, getString(R.string.action_uncategorized));
break;
}
case RECENT: {
subtitle = getString(R.string.search_in_all);
break;
}
case DEFAULT_CATEGORY:
default: {
Category category = selectedCategory.getCategory();
subtitle = getString(R.string.search_in_category, NoteUtil.extendCategory(category == null ? "" : category.getTitle()));
break;
} }
} else if (navigationSelection.favorite != null && navigationSelection.favorite) {
subtitle = getString(R.string.search_in_category, getString(R.string.label_favorites));
} else {
subtitle = getString(R.string.search_in_all);
} }
activityBinding.searchText.setText(subtitle); activityBinding.searchText.setText(subtitle);
}); });
@ -223,12 +237,12 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
categoryAdapterSelectedItem = ADAPTER_KEY_RECENT; categoryAdapterSelectedItem = ADAPTER_KEY_RECENT;
} else if (ACTION_FAVORITES.equals(getIntent().getAction())) { } else if (ACTION_FAVORITES.equals(getIntent().getAction())) {
categoryAdapterSelectedItem = ADAPTER_KEY_STARRED; categoryAdapterSelectedItem = ADAPTER_KEY_STARRED;
mainViewModel.postSelectedCategory(new OldCategory(null, true)); mainViewModel.postSelectedCategory(new NavigationCategory(FAVORITES));
} }
} else { } else {
Object savedCategory = savedInstanceState.getSerializable(SAVED_STATE_NAVIGATION_SELECTION); Object savedCategory = savedInstanceState.getSerializable(SAVED_STATE_NAVIGATION_SELECTION);
if (savedCategory != null) { if (savedCategory != null) {
mainViewModel.postSelectedCategory((OldCategory) savedCategory); mainViewModel.postSelectedCategory((NavigationCategory) savedCategory);
} }
navigationOpen = savedInstanceState.getString(SAVED_STATE_NAVIGATION_OPEN); navigationOpen = savedInstanceState.getString(SAVED_STATE_NAVIGATION_OPEN);
categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION); categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION);
@ -475,21 +489,25 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
adapterCategories.setSelectedItem(item.id); adapterCategories.setSelectedItem(item.id);
// update current selection // update current selection
if (itemRecent.equals(item)) { if (itemRecent.equals(item)) {
mainViewModel.postSelectedCategory(new OldCategory(null, null)); mainViewModel.postSelectedCategory(new NavigationCategory(RECENT));
} else if (itemFavorites.equals(item)) { } else if (itemFavorites.equals(item)) {
mainViewModel.postSelectedCategory(new OldCategory(null, true)); mainViewModel.postSelectedCategory(new NavigationCategory(FAVORITES));
} else if (itemUncategorized != null && itemUncategorized.equals(item)) { } else if (itemUncategorized != null && itemUncategorized.equals(item)) {
mainViewModel.postSelectedCategory(new OldCategory("", null)); mainViewModel.postSelectedCategory(new NavigationCategory(UNCATEGORIZED));
} else { } else {
mainViewModel.postSelectedCategory(new OldCategory(item.label, null)); mainViewModel.postSelectedCategory(new NavigationCategory(db.getCategoryDao().getCategoryByTitle(localAccount.getId(), item.label)));
} }
// auto-close sub-folder in Navigation if selection is outside of that folder // auto-close sub-folder in Navigation if selection is outside of that folder
if (navigationOpen != null) { if (navigationOpen != null && navigationSelection.getType() == DEFAULT_CATEGORY) {
int slashIndex = navigationSelection.category == null ? -1 : navigationSelection.category.indexOf('/'); Category category = navigationSelection.getCategory();
String rootCategory = slashIndex < 0 ? navigationSelection.category : navigationSelection.category.substring(0, slashIndex); if (category != null) {
if (!navigationOpen.equals(rootCategory)) { String title = category.getTitle();
navigationOpen = null; int slashIndex = title == null ? -1 : title.indexOf('/');
String rootCategory = slashIndex < 0 ? title : title.substring(0, slashIndex);
if (!navigationOpen.equals(rootCategory)) {
navigationOpen = null;
}
} }
} }

View file

@ -1,32 +1,35 @@
package it.niedermann.owncloud.notes.main; package it.niedermann.owncloud.notes.main;
import android.app.Application; import android.app.Application;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.arch.core.util.Function;
import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData; import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import java.util.List; import java.util.List;
import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.persistence.NotesDatabase;
import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.Category;
import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory;
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
import it.niedermann.owncloud.notes.shared.model.Item; import it.niedermann.owncloud.notes.shared.model.Item;
import it.niedermann.owncloud.notes.shared.model.OldCategory; import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import static androidx.lifecycle.Transformations.distinctUntilChanged; import static androidx.lifecycle.Transformations.distinctUntilChanged;
import static androidx.lifecycle.Transformations.map; import static androidx.lifecycle.Transformations.map;
import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByCategory; import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByCategory;
import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByInitials; import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByInitials;
import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByTime; import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByTime;
import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.RECENT;
public class MainViewModel extends AndroidViewModel { public class MainViewModel extends AndroidViewModel {
private static final String TAG = MainViewModel.class.getSimpleName();
@NonNull @NonNull
private NotesDatabase db; private NotesDatabase db;
@ -35,7 +38,7 @@ public class MainViewModel extends AndroidViewModel {
@NonNull @NonNull
private MutableLiveData<String> searchTerm = new MutableLiveData<>(); private MutableLiveData<String> searchTerm = new MutableLiveData<>();
@NonNull @NonNull
private MutableLiveData<OldCategory> selectedCategory = new MutableLiveData<>(new OldCategory(null, null)); private MutableLiveData<NavigationCategory> selectedCategory = new MutableLiveData<>(new NavigationCategory(RECENT));
public MainViewModel(@NonNull Application application) { public MainViewModel(@NonNull Application application) {
super(application); super(application);
@ -50,7 +53,7 @@ public class MainViewModel extends AndroidViewModel {
this.searchTerm.postValue(searchTerm); this.searchTerm.postValue(searchTerm);
} }
public void postSelectedCategory(@NonNull OldCategory selectedCategory) { public void postSelectedCategory(@NonNull NavigationCategory selectedCategory) {
this.selectedCategory.postValue(selectedCategory); this.selectedCategory.postValue(selectedCategory);
} }
@ -62,7 +65,7 @@ public class MainViewModel extends AndroidViewModel {
return searchTerm; return searchTerm;
} }
public LiveData<OldCategory> getSelectedCategory() { public LiveData<NavigationCategory> getSelectedCategory() {
return selectedCategory; return selectedCategory;
} }
@ -76,33 +79,53 @@ public class MainViewModel extends AndroidViewModel {
public LiveData<List<Item>> getNotesListLiveData() { public LiveData<List<Item>> getNotesListLiveData() {
Account currentAccount = getCurrentAccount().getValue(); Account currentAccount = getCurrentAccount().getValue();
OldCategory selectedCategory = getSelectedCategory().getValue(); NavigationCategory selectedCategory = getSelectedCategory().getValue();
LiveData<List<NoteWithCategory>> fromDatabase; LiveData<List<NoteWithCategory>> fromDatabase;
if (currentAccount != null && selectedCategory != null) { if (currentAccount != null && selectedCategory != null) {
Long accountId = currentAccount.getId(); Long accountId = currentAccount.getId();
CategorySortingMethod sortingMethod = db.getCategoryOrder(accountId, selectedCategory); CategorySortingMethod sortingMethod = db.getCategoryOrder(accountId, selectedCategory);
String searchQuery = getSearchTerm().getValue(); String searchQuery = getSearchTerm().getValue();
searchQuery = searchQuery == null ? "%" : "%" + searchQuery.trim() + "%"; searchQuery = searchQuery == null ? "%" : "%" + searchQuery.trim() + "%";
if (Boolean.TRUE.equals(selectedCategory.favorite)) { // Favorites switch (selectedCategory.getType()) {
fromDatabase = db.getNoteDao().searchNotesFavorites(accountId, searchQuery, sortingMethod.getSorder()); case FAVORITES: {
} else if (selectedCategory.category != null && selectedCategory.category.length() == 0) { // Uncategorized fromDatabase = db.getNoteDao().searchNotesFavorites(accountId, searchQuery, sortingMethod.getSorder());
fromDatabase = db.getNoteDao().searchNotesUncategorized(accountId, searchQuery, sortingMethod.getSorder()); break;
} else if( selectedCategory.category == null && selectedCategory.favorite == null) { // Recent }
fromDatabase = db.getNoteDao().searchNotesAll(accountId, searchQuery, sortingMethod.getSorder()); case UNCATEGORIZED: {
} else { // A special category fromDatabase = db.getNoteDao().searchNotesUncategorized(accountId, searchQuery, sortingMethod.getSorder());
fromDatabase = db.getNoteDao().searchNotesByCategory(accountId, searchQuery, selectedCategory.category, sortingMethod.getSorder()); break;
}
case RECENT: {
fromDatabase = db.getNoteDao().searchNotesAll(accountId, searchQuery, sortingMethod.getSorder());
break;
}
case DEFAULT_CATEGORY:
default: {
Category category = selectedCategory.getCategory();
fromDatabase = db.getNoteDao().searchNotesByCategory(accountId, searchQuery, category == null ? "" : category.getTitle(), sortingMethod.getSorder());
break;
}
} }
return distinctUntilChanged( return distinctUntilChanged(
map(fromDatabase, noteList -> { map(fromDatabase, noteList -> {
if (selectedCategory.category == null) { //noinspection SwitchStatementWithTooFewBranches
if (sortingMethod == CategorySortingMethod.SORT_MODIFIED_DESC) { switch (selectedCategory.getType()) {
return fillListByTime(getApplication(), noteList); case DEFAULT_CATEGORY: {
} else { Category category = selectedCategory.getCategory();
return fillListByInitials(getApplication(), noteList); if (category != null) {
return fillListByCategory(noteList, category.getTitle());
} else {
Log.e(TAG, "Tried to fill list by category, but category is null.");
}
}
default: {
if (sortingMethod == CategorySortingMethod.SORT_MODIFIED_DESC) {
return fillListByTime(getApplication(), noteList);
} else {
return fillListByInitials(getApplication(), noteList);
}
} }
} else {
return fillListByCategory(noteList, selectedCategory.category);
} }
}) })
); );

View file

@ -5,7 +5,6 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager; import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.graphics.drawable.Icon; import android.graphics.drawable.Icon;
import android.os.Build; import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
@ -37,14 +36,12 @@ import java.util.Map;
import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.edit.EditNoteActivity; import it.niedermann.owncloud.notes.edit.EditNoteActivity;
import it.niedermann.owncloud.notes.main.NavigationAdapter;
import it.niedermann.owncloud.notes.persistence.dao.AccountDao; import it.niedermann.owncloud.notes.persistence.dao.AccountDao;
import it.niedermann.owncloud.notes.persistence.dao.CategoryDao; import it.niedermann.owncloud.notes.persistence.dao.CategoryDao;
import it.niedermann.owncloud.notes.persistence.dao.NoteDao; import it.niedermann.owncloud.notes.persistence.dao.NoteDao;
import it.niedermann.owncloud.notes.persistence.dao.WidgetNotesListDao; import it.niedermann.owncloud.notes.persistence.dao.WidgetNotesListDao;
import it.niedermann.owncloud.notes.persistence.dao.WidgetSingleNoteDao; import it.niedermann.owncloud.notes.persistence.dao.WidgetSingleNoteDao;
import it.niedermann.owncloud.notes.persistence.entity.Category; import it.niedermann.owncloud.notes.persistence.entity.Category;
import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount;
import it.niedermann.owncloud.notes.persistence.entity.Converters; import it.niedermann.owncloud.notes.persistence.entity.Converters;
import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.Note;
@ -65,8 +62,9 @@ import it.niedermann.owncloud.notes.shared.model.ApiVersion;
import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.model.Capabilities;
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.DBStatus;
import it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType;
import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.model.ISyncCallback;
import it.niedermann.owncloud.notes.shared.model.OldCategory; import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import it.niedermann.owncloud.notes.shared.util.NoteUtil; import it.niedermann.owncloud.notes.shared.util.NoteUtil;
import static it.niedermann.owncloud.notes.edit.EditNoteActivity.ACTION_SHORTCUT; import static it.niedermann.owncloud.notes.edit.EditNoteActivity.ACTION_SHORTCUT;
@ -469,36 +467,40 @@ public abstract class NotesDatabase extends RoomDatabase {
* The user can determine use which sorting method to show the notes for a category. * The user can determine use which sorting method to show the notes for a category.
* When the user changes the sorting method, this method should be called. * When the user changes the sorting method, this method should be called.
* *
* @param accountId The user accountID * @param accountId The user accountID
* @param category The category to be modified * @param selectedCategory The category to be modified
* @param sortingMethod The sorting method in {@link CategorySortingMethod} enum format * @param sortingMethod The sorting method in {@link CategorySortingMethod} enum format
*/ */
public void modifyCategoryOrder(long accountId, OldCategory category, CategorySortingMethod sortingMethod) { public void modifyCategoryOrder(long accountId, NavigationCategory selectedCategory, CategorySortingMethod sortingMethod) {
validateAccountId(accountId); validateAccountId(accountId);
final Context ctx = context.getApplicationContext(); final Context ctx = context.getApplicationContext();
final SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(ctx).edit(); final SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(ctx).edit();
int orderIndex = sortingMethod.getCSMID(); int orderIndex = sortingMethod.getCSMID();
if (category.category == null) {
if (category.favorite != null && category.favorite) { switch (selectedCategory.getType()) {
// Favorite case FAVORITES: {
sp.putInt(ctx.getString(R.string.action_sorting_method) + sp.putInt(ctx.getString(R.string.action_sorting_method) + ' ' + ctx.getString(R.string.label_favorites), orderIndex);
' ' + ctx.getString(R.string.label_favorites), break;
orderIndex); }
} else { case UNCATEGORIZED: {
// All notes sp.putInt(ctx.getString(R.string.action_sorting_method) + ' ' + ctx.getString(R.string.action_uncategorized), orderIndex);
sp.putInt(ctx.getString(R.string.action_sorting_method) + break;
' ' + ctx.getString(R.string.label_all_notes), }
orderIndex); case RECENT: {
sp.putInt(ctx.getString(R.string.action_sorting_method) + ' ' + ctx.getString(R.string.label_all_notes), orderIndex);
break;
}
case DEFAULT_CATEGORY:
default: {
Category category = selectedCategory.getCategory();
if(category != null) {
getCategoryDao().modifyCategoryOrder(accountId, category.getId(), sortingMethod);
} else {
Log.e(TAG, "Tried to modify category order for " + ENavigationCategoryType.DEFAULT_CATEGORY + "but category is null.");
}
break;
} }
} else if (category.category.isEmpty()) {
// Uncategorized
sp.putInt(ctx.getString(R.string.action_sorting_method) +
' ' + ctx.getString(R.string.action_uncategorized),
orderIndex);
} else {
getCategoryDao().modifyCategoryOrderByTitle(accountId, category.category, sortingMethod);
return;
} }
sp.apply(); sp.apply();
} }
@ -510,36 +512,40 @@ public abstract class NotesDatabase extends RoomDatabase {
* The sorting method of the category can be used to decide * The sorting method of the category can be used to decide
* to use which sorting method to show the notes for each categories. * to use which sorting method to show the notes for each categories.
* *
* @param accountId The user accountID * @param accountId The user accountID
* @param category The category * @param selectedCategory The category
* @return The sorting method in CategorySortingMethod enum format * @return The sorting method in CategorySortingMethod enum format
*/ */
public CategorySortingMethod getCategoryOrder(long accountId, OldCategory category) { public CategorySortingMethod getCategoryOrder(long accountId, NavigationCategory selectedCategory) {
validateAccountId(accountId); validateAccountId(accountId);
final Context ctx = context.getApplicationContext(); final Context ctx = context.getApplicationContext();
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(ctx); final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(ctx);
int orderIndex; int orderIndex;
if (category.category == null) { switch (selectedCategory.getType()) {
if (category.favorite != null && category.favorite) { case FAVORITES: {
// Favorite orderIndex = sp.getInt(ctx.getString(R.string.action_sorting_method) + ' ' + ctx.getString(R.string.label_favorites), 0);
orderIndex = sp.getInt(ctx.getString(R.string.action_sorting_method) + break;
' ' + ctx.getString(R.string.label_favorites), }
0); case UNCATEGORIZED: {
} else { orderIndex = sp.getInt(ctx.getString(R.string.action_sorting_method) + ' ' + ctx.getString(R.string.action_uncategorized),0);
// All notes break;
orderIndex = sp.getInt(ctx.getString(R.string.action_sorting_method) + }
' ' + ctx.getString(R.string.label_all_notes), case RECENT: {
0); orderIndex = sp.getInt(ctx.getString(R.string.action_sorting_method) + ' ' + ctx.getString(R.string.label_all_notes), 0);
break;
}
case DEFAULT_CATEGORY:
default: {
Category category = selectedCategory.getCategory();
if(category != null) {
return getCategoryDao().getCategoryOrder(accountId, category.getId());
} else {
Log.e(TAG, "Cannot read " + CategorySortingMethod.class.getSimpleName() + " for " + ENavigationCategoryType.DEFAULT_CATEGORY + ".");
return CategorySortingMethod.SORT_MODIFIED_DESC;
}
} }
} else if (category.category.isEmpty()) {
// Uncategorized
orderIndex = sp.getInt(ctx.getString(R.string.action_sorting_method) +
' ' + ctx.getString(R.string.action_uncategorized),
0);
} else {
return getCategoryDao().getCategoryOrderByTitle(accountId, category.category);
} }
return CategorySortingMethod.getCSM(orderIndex); return CategorySortingMethod.getCSM(orderIndex);

View file

@ -34,6 +34,9 @@ public interface CategoryDao {
@Query("SELECT id FROM CATEGORY WHERE accountId = :accountId AND title = :title") @Query("SELECT id FROM CATEGORY WHERE accountId = :accountId AND title = :title")
Long getCategoryIdByTitle(long accountId, String title); Long getCategoryIdByTitle(long accountId, String title);
@Query("SELECT * FROM CATEGORY WHERE accountId = :accountId AND title = :title")
Category getCategoryByTitle(long accountId, String title);
/** /**
* This method is used to modify the sorting method for one category by title. * This method is used to modify the sorting method for one category by title.
@ -41,23 +44,23 @@ public interface CategoryDao {
* When the user changes the sorting method, this method should be called. * When the user changes the sorting method, this method should be called.
* *
* @param accountId The user accountID * @param accountId The user accountID
* @param categoryTitle The category title * @param categoryId The category id
* @param sortingMethod The sorting method in {@link CategorySortingMethod} enum format * @param sortingMethod The sorting method in {@link CategorySortingMethod} enum format
*/ */
@Query("UPDATE CATEGORY SET sortingMethod = :sortingMethod WHERE id = (SELECT id FROM CATEGORY WHERE accountId = :accountId AND title = :categoryTitle)") @Query("UPDATE CATEGORY SET sortingMethod = :sortingMethod WHERE id = :categoryId AND accountId = :accountId")
void modifyCategoryOrderByTitle(long accountId, String categoryTitle, CategorySortingMethod sortingMethod); void modifyCategoryOrder(long accountId, long categoryId, CategorySortingMethod sortingMethod);
/** /**
* This function is used to get the sorting method of a category by title. * This function is used to get the sorting method of a category by title.
* The sorting method of the category can be used to decide * The sorting method of the category can be used to decide
* to use which sorting method to show the notes for each categories. * to use which sorting method to show the notes for each categories.
* *
* @param accountId The user accountID * @param accountId The user accountID
* @param categoryTitle The category title * @param categoryId The category title
* @return The sorting method in {@link CategorySortingMethod} enum format * @return The sorting method in {@link CategorySortingMethod} enum format
*/ */
@Query("SELECT sortingMethod FROM CATEGORY WHERE accountId = :accountId AND title = :categoryTitle") @Query("SELECT sortingMethod FROM CATEGORY WHERE accountId = :accountId AND id = :categoryId")
CategorySortingMethod getCategoryOrderByTitle(long accountId, String categoryTitle); CategorySortingMethod getCategoryOrder(long accountId, long categoryId);
@Query("SELECT title FROM CATEGORY WHERE id = :id") @Query("SELECT title FROM CATEGORY WHERE id = :id")
String getCategoryTitleById(long id); String getCategoryTitleById(long id);

View file

@ -0,0 +1,9 @@
package it.niedermann.owncloud.notes.shared.model;
public enum ENavigationCategoryType {
RECENT,
FAVORITES,
UNCATEGORIZED,
DEFAULT_CATEGORY
}

View file

@ -0,0 +1,39 @@
package it.niedermann.owncloud.notes.shared.model;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.Serializable;
import it.niedermann.owncloud.notes.persistence.entity.Category;
public class NavigationCategory implements Serializable {
@NonNull
private final ENavigationCategoryType type;
@Nullable
private final Category category;
public NavigationCategory(@NonNull ENavigationCategoryType type) {
if (type == ENavigationCategoryType.DEFAULT_CATEGORY) {
throw new IllegalArgumentException("If you want to provide a " + ENavigationCategoryType.DEFAULT_CATEGORY + ", call the constructor with a " + Category.class.getSimpleName());
}
this.type = type;
this.category = null;
}
public NavigationCategory(@NonNull Category category) {
this.type = ENavigationCategoryType.DEFAULT_CATEGORY;
this.category = category;
}
@NonNull
public ENavigationCategoryType getType() {
return type;
}
@Nullable
public Category getCategory() {
return category;
}
}

View file

@ -1,18 +0,0 @@
package it.niedermann.owncloud.notes.shared.model;
import androidx.annotation.Nullable;
import java.io.Serializable;
public class OldCategory implements Serializable {
@Nullable
public final String category;
@Nullable
public final Boolean favorite;
public OldCategory(@Nullable String category, @Nullable Boolean favorite) {
this.category = category;
this.favorite = favorite;
}
}

View file

@ -22,7 +22,8 @@ import it.niedermann.owncloud.notes.persistence.NotesDatabase;
import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData; import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData;
import it.niedermann.owncloud.notes.preferences.DarkModeSetting; import it.niedermann.owncloud.notes.preferences.DarkModeSetting;
import it.niedermann.owncloud.notes.shared.model.OldCategory; import it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType;
import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import static it.niedermann.owncloud.notes.edit.EditNoteActivity.PARAM_CATEGORY; import static it.niedermann.owncloud.notes.edit.EditNoteActivity.PARAM_CATEGORY;
import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_ALL; import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_ALL;
@ -70,7 +71,10 @@ public class NoteListWidget extends AppWidgetProvider {
// Launch create note activity if user taps "+" icon on header // Launch create note activity if user taps "+" icon on header
PendingIntent newNoteI = PendingIntent.getActivity(context, (PENDING_INTENT_NEW_NOTE_RQ + appWidgetId), PendingIntent newNoteI = PendingIntent.getActivity(context, (PENDING_INTENT_NEW_NOTE_RQ + appWidgetId),
new Intent(context, EditNoteActivity.class).putExtra(PARAM_CATEGORY, new OldCategory(category, data.getMode() == MODE_DISPLAY_STARRED)), new Intent(context, EditNoteActivity.class).putExtra(PARAM_CATEGORY,
data.getMode() == MODE_DISPLAY_STARRED
? new NavigationCategory(ENavigationCategoryType.FAVORITES)
: new NavigationCategory(db.getCategoryDao().getCategoryByTitle(localAccount.getId(), category))),
PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent templatePI = PendingIntent.getActivity(context, PENDING_INTENT_EDIT_NOTE_RQ, PendingIntent templatePI = PendingIntent.getActivity(context, PENDING_INTENT_EDIT_NOTE_RQ,

View file

@ -6,7 +6,7 @@ import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class OldCategorySortingMethodTest { public class NavigationCategorySortingMethodTest {
@Test @Test
public void getCSMID() { public void getCSMID() {