diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-12-29 17:07:07 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-12-29 17:07:07 +0300 |
commit | 4bece6a5e32231610efa7c27a55b07abe93b5247 (patch) | |
tree | f4833f2b387d6b402f2d075db66f8c4c066c4de8 /app/src/main/java/it/niedermann | |
parent | bb542a887f9b90c3280332469df80542620edbab (diff) |
Denormalize database to eleminate artifical category ID
see https://github.com/stefan-niedermann/nextcloud-notes/pull/967#issuecomment-751854626
Diffstat (limited to 'app/src/main/java/it/niedermann')
42 files changed, 502 insertions, 676 deletions
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/AppendToNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/AppendToNoteActivity.java index 96f696ad..191f0d47 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/AppendToNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/AppendToNoteActivity.java @@ -11,7 +11,7 @@ import androidx.appcompat.app.ActionBar; import androidx.lifecycle.LiveData; import it.niedermann.owncloud.notes.main.MainActivity; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; public class AppendToNoteActivity extends MainActivity { @@ -37,7 +37,7 @@ public class AppendToNoteActivity extends MainActivity { @Override public void onNoteClick(int position, View v) { if (receivedText != null && receivedText.length() > 0) { - final LiveData<NoteWithCategory> fullNote$ = mainViewModel.getFullNoteWithCategory(((NoteWithCategory) adapter.getItem(position)).getId()); + final LiveData<Note> fullNote$ = mainViewModel.getFullNote(((Note) adapter.getItem(position)).getId()); fullNote$.observe(this, (fullNote) -> { fullNote$.removeObservers(this); final String oldContent = fullNote.getContent(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java index 63977ff1..314f96a6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java @@ -44,7 +44,6 @@ import it.niedermann.owncloud.notes.edit.title.EditTitleDialogFragment.EditTitle import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.ApiVersion; import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.ISyncCallback; @@ -72,10 +71,10 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego private Account localAccount; - protected NoteWithCategory note; + protected Note note; // TODO do we really need this? The reference to note is currently the same @Nullable - private NoteWithCategory originalNote; + private Note originalNote; private int originalScrollY; protected NotesDatabase db; private NoteFragmentListener listener; @@ -111,18 +110,18 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego SingleAccountHelper.setCurrentAccount(requireActivity().getApplicationContext(), localAccount.getAccountName()); } isNew = false; - note = originalNote = db.getNoteDao().getFullNoteWithCategory(id); + note = originalNote = db.getNoteDao().getNoteById(id); } else { - NoteWithCategory cloudNote = (NoteWithCategory) requireArguments().getSerializable(PARAM_NEWNOTE); + Note cloudNote = (Note) requireArguments().getSerializable(PARAM_NEWNOTE); String content = requireArguments().getString(PARAM_CONTENT); if (cloudNote == null) { if (content == null) { throw new IllegalArgumentException(PARAM_NOTE_ID + " is not given, argument " + PARAM_NEWNOTE + " is missing and " + PARAM_CONTENT + " is missing."); } else { - note = new NoteWithCategory(new Note(-1, -1L, Calendar.getInstance(), NoteUtil.generateNoteTitle(content), content, false, getString(R.string.category_readonly), DBStatus.VOID, -1, "", 0)); + note = new Note(-1, -1L, Calendar.getInstance(), NoteUtil.generateNoteTitle(content), content, getString(R.string.category_readonly), false, null, DBStatus.VOID, -1, "", 0); } } else { - final LiveData<NoteWithCategory> createLiveData = db.addNoteAndSync(localAccount, cloudNote); + final LiveData<Note> createLiveData = db.addNoteAndSync(localAccount, cloudNote); createLiveData.observe(requireActivity(), (createdNote) -> { note = createdNote; originalNote = null; @@ -131,8 +130,8 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego } } } else { - note = (NoteWithCategory) savedInstanceState.getSerializable(SAVEDKEY_NOTE); - originalNote = (NoteWithCategory) savedInstanceState.getSerializable(SAVEDKEY_ORIGINAL_NOTE); + note = (Note) savedInstanceState.getSerializable(SAVEDKEY_NOTE); + originalNote = (Note) savedInstanceState.getSerializable(SAVEDKEY_ORIGINAL_NOTE); } setHasOptionsMenu(true); } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { @@ -150,7 +149,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego if (scrollView != null) { scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> { if (scrollView.getScrollY() > 0) { - note.getNote().setScrollY(scrollView.getScrollY()); + note.setScrollY(scrollView.getScrollY()); } }); } @@ -356,7 +355,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego @Override public void onTitleEdited(String newTitle) { titleModified = true; - note.getNote().setTitle(newTitle); + note.setTitle(newTitle); note = db.updateNoteAndSync(localAccount, note, note.getContent(), newTitle, null); listener.onNoteUpdated(note); } @@ -402,6 +401,6 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego public interface NoteFragmentListener { void close(); - void onNoteUpdated(NoteWithCategory note); + void onNoteUpdated(Note note); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java index 92c091da..5b4adc2c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java @@ -26,9 +26,7 @@ import it.niedermann.owncloud.notes.accountpicker.AccountPickerListener; import it.niedermann.owncloud.notes.databinding.ActivityEditBinding; import it.niedermann.owncloud.notes.edit.category.CategoryViewModel; 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.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.NavigationCategory; import it.niedermann.owncloud.notes.shared.util.NoteUtil; @@ -164,12 +162,14 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment private void launchNewNote() { Intent intent = getIntent(); - String categoryTitle = null; + String categoryTitle = ""; boolean favorite = false; if (intent.hasExtra(PARAM_CATEGORY)) { - NavigationCategory categoryPreselection = (NavigationCategory) Objects.requireNonNull(intent.getSerializableExtra(PARAM_CATEGORY)); - Category category = categoryPreselection.getCategory(); - categoryTitle = category == null ? "" : category.getTitle(); + final NavigationCategory categoryPreselection = (NavigationCategory) Objects.requireNonNull(intent.getSerializableExtra(PARAM_CATEGORY)); + final String category = categoryPreselection.getCategory(); + if(category != null) { + categoryTitle = category; + } favorite = categoryPreselection.getType() == FAVORITES; } @@ -188,7 +188,7 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment if (content == null) { content = ""; } - NoteWithCategory newNote = new NoteWithCategory(new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, favorite, null), categoryTitle); + Note newNote = new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, categoryTitle, favorite, null); fragment = NoteEditFragment.newInstanceWithNewNote(newNote); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_view, fragment).commit(); } @@ -259,7 +259,7 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment } @Override - public void onNoteUpdated(NoteWithCategory note) { + public void onNoteUpdated(Note note) { if (note != null) { binding.toolbar.setTitle(note.getTitle()); if (TextUtils.isEmpty(note.getCategory())) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java index c2cb62a1..d329e916 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java @@ -27,7 +27,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.databinding.FragmentNoteEditBinding; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import static androidx.core.view.ViewCompat.isAttachedToWindow; @@ -69,7 +69,7 @@ public class NoteEditFragment extends SearchableBaseNoteFragment { return f; } - public static NoteEditFragment newInstanceWithNewNote(NoteWithCategory newNote) { + public static NoteEditFragment newInstanceWithNewNote(Note newNote) { NoteEditFragment f = new NoteEditFragment(); Bundle b = new Bundle(); b.putSerializable(PARAM_NEWNOTE, newNote); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java index 5758afe8..27809451 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java @@ -170,7 +170,7 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O }) .build()); - TextProcessorChain chain = defaultTextProcessorChain(note.getNote()); + TextProcessorChain chain = defaultTextProcessorChain(note); try { binding.singleNoteContent.setText(parseCompat(markdownProcessor, chain.apply(note.getContent()))); } catch (StringIndexOutOfBoundsException e) { @@ -210,10 +210,10 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O if (db.getNoteServerSyncHelper().isSyncPossible() && SSOUtil.isConfigured(getContext())) { binding.swiperefreshlayout.setRefreshing(true); try { - TextProcessorChain chain = defaultTextProcessorChain(note.getNote()); + TextProcessorChain chain = defaultTextProcessorChain(note); Account account = db.getAccountDao().getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(requireContext()).name); db.getNoteServerSyncHelper().addCallbackPull(account, () -> { - note = db.getNoteDao().getFullNoteWithCategory(note.getId()); + note = db.getNoteDao().getNoteById(note.getId()); changedText = note.getContent(); binding.singleNoteContent.setText(parseCompat(markdownProcessor, chain.apply(note.getContent()))); binding.swiperefreshlayout.setRefreshing(false); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/category/CategoryViewModel.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/category/CategoryViewModel.java index e3c61acc..d41c149c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/category/CategoryViewModel.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/category/CategoryViewModel.java @@ -36,7 +36,7 @@ public class CategoryViewModel extends AndroidViewModel { @NonNull public LiveData<List<NavigationItem.CategoryNavigationItem>> getCategories(long accountId) { return switchMap(this.searchTerm, searchTerm -> - map(db.getCategoryDao().searchCategories(accountId, TextUtils.isEmpty(searchTerm) ? "%" : "%" + searchTerm + "%"), + map(db.getNoteDao().searchCategories(accountId, TextUtils.isEmpty(searchTerm) ? "%" : "%" + searchTerm + "%"), categories -> convertToCategoryNavigationItem(getApplication(), categories))); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java index 3b84fbc6..09d3380f 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java @@ -33,8 +33,16 @@ public class ExceptionDialogFragment extends AppCompatDialogFragment { final Bundle args = getArguments(); if (args != null) { final Object throwablesArgument = args.getSerializable(KEY_THROWABLES); - if (throwablesArgument != null) { - throwables.addAll((ArrayList<Throwable>) throwablesArgument); + if (throwablesArgument instanceof Iterable<?>) { + for (Object arg : (Iterable<?>) throwablesArgument) { + if (arg instanceof Throwable) { + throwables.add((Throwable) arg); + } else { + throw new IllegalArgumentException("Expected all " + KEY_THROWABLES + " to be instance of " + Throwable.class.getSimpleName()); + } + } + } else { + throw new IllegalArgumentException(KEY_THROWABLES + " needs to be an " + Iterable.class.getSimpleName() + "<" + Throwable.class.getSimpleName() + ">"); } } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java index cae371d5..63a38dbf 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java @@ -72,8 +72,7 @@ import it.niedermann.owncloud.notes.main.navigation.NavigationItem; import it.niedermann.owncloud.notes.persistence.CapabilitiesClient; import it.niedermann.owncloud.notes.persistence.CapabilitiesWorker; 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.Note; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; import it.niedermann.owncloud.notes.shared.model.NavigationCategory; @@ -195,11 +194,11 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A } case DEFAULT_CATEGORY: default: { - final Category category = selectedCategory.getCategory(); + final String category = selectedCategory.getCategory(); if (category == null) { throw new IllegalStateException(NavigationCategory.class.getSimpleName() + " type is " + DEFAULT_CATEGORY + ", but category is null."); } - activityBinding.searchText.setText(getString(R.string.search_in_category, NoteUtil.extendCategory(category.getTitle()))); + activityBinding.searchText.setText(getString(R.string.search_in_category, NoteUtil.extendCategory(category))); break; } } @@ -228,7 +227,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A if (notes .stream() .filter(item -> !item.isSection()) - .map(item -> (NoteWithCategory) item) + .map(item -> (Note) item) .noneMatch(item -> item.getId() == id)) { deletedNotes.add(id); } @@ -467,7 +466,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A } default: { if (item.getClass() == NavigationItem.CategoryNavigationItem.class) { - mainViewModel.postSelectedCategory(new NavigationCategory(mainViewModel.getCategory(((NavigationItem.CategoryNavigationItem) item).categoryId))); + mainViewModel.postSelectedCategory(new NavigationCategory(((NavigationItem.CategoryNavigationItem) item).accountId, ((NavigationItem.CategoryNavigationItem) item).category)); } else { throw new IllegalStateException(NavigationItem.class.getSimpleName() + " type is " + DEFAULT_CATEGORY + ", but item is not of type " + NavigationItem.CategoryNavigationItem.class.getSimpleName() + "."); } @@ -633,7 +632,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A public void onNoteClick(int position, View v) { boolean hasCheckedItems = tracker.getSelection().size() > 0; if (!hasCheckedItems) { - NoteWithCategory note = (NoteWithCategory) adapter.getItem(position); + Note note = (Note) adapter.getItem(position); Intent intent = new Intent(getApplicationContext(), EditNoteActivity.class); intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId()); startActivityForResult(intent, show_single_note_cmd); @@ -642,7 +641,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A @Override public void onNoteFavoriteClick(int position, View view) { - LiveData<Void> toggleLiveData = mainViewModel.toggleFavoriteAndSync(((NoteWithCategory) adapter.getItem(position)).getId()); + LiveData<Void> toggleLiveData = mainViewModel.toggleFavoriteAndSync(((Note) adapter.getItem(position)).getId()); toggleLiveData.observe(this, (next) -> toggleLiveData.removeObservers(this)); } @@ -683,7 +682,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A @Override public void onAccountPicked(@NonNull Account account) { for (Long noteId : tracker.getSelection()) { - final LiveData<NoteWithCategory> moveLiveData = mainViewModel.moveNoteToAnotherAccount(account, noteId); + final LiveData<Note> moveLiveData = mainViewModel.moveNoteToAnotherAccount(account, noteId); moveLiveData.observe(this, (v) -> { tracker.deselect(noteId); moveLiveData.removeObservers(this); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java b/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java index 25033335..5584bd24 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java @@ -13,7 +13,9 @@ import androidx.annotation.WorkerThread; import androidx.arch.core.util.Function; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; +import androidx.lifecycle.MediatorLiveData; import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; import androidx.lifecycle.SavedStateHandle; import com.nextcloud.android.sso.AccountImporter; @@ -36,9 +38,8 @@ import it.niedermann.owncloud.notes.persistence.CapabilitiesClient; import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper; import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.persistence.entity.Account; -import it.niedermann.owncloud.notes.persistence.entity.Category; import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.SingleNoteWidgetData; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; @@ -99,6 +100,7 @@ public class MainViewModel extends AndroidViewModel { final NavigationCategory selectedCategory = state.get(KEY_SELECTED_CATEGORY); if (selectedCategory != null) { postSelectedCategory(selectedCategory); + Log.v(TAG, "[restoreInstanceState] - selectedCategory: " + selectedCategory); } postExpandedCategory(state.get(KEY_EXPANDED_CATEGORY)); } @@ -112,9 +114,15 @@ public class MainViewModel extends AndroidViewModel { state.set(KEY_CURRENT_ACCOUNT, account); BrandingUtil.saveBrandColors(getApplication(), account.getColor(), account.getTextColor()); SingleAccountHelper.setCurrentAccount(getApplication(), account.getAccountName()); - this.currentAccount.setValue(account); - this.searchTerm.setValue(""); - this.selectedCategory.setValue(new NavigationCategory(RECENT)); + + final Account currentAccount = this.currentAccount.getValue(); + // If only ETag or colors change, we must not reset the navigation + // TODO in the long term we should store the last NavigationCategory for each Account + if (currentAccount == null || currentAccount.getId() != account.getId()) { + this.currentAccount.setValue(account); + this.searchTerm.setValue(""); + this.selectedCategory.setValue(new NavigationCategory(RECENT)); + } } @NonNull @@ -134,6 +142,7 @@ public class MainViewModel extends AndroidViewModel { public void postSelectedCategory(@NonNull NavigationCategory selectedCategory) { state.set(KEY_SELECTED_CATEGORY, selectedCategory); + Log.v(TAG, "[postSelectedCategory] - selectedCategory: " + selectedCategory); this.selectedCategory.postValue(selectedCategory); // Close sub categories @@ -146,14 +155,13 @@ public class MainViewModel extends AndroidViewModel { } case DEFAULT_CATEGORY: default: { - Category category = selectedCategory.getCategory(); + String category = selectedCategory.getCategory(); if (category == null) { postExpandedCategory(null); Log.e(TAG, "navigation selection is a " + DEFAULT_CATEGORY + ", but the contained category is null."); } else { - String title = category.getTitle(); - int slashIndex = title.indexOf('/'); - String rootCategory = slashIndex < 0 ? title : title.substring(0, slashIndex); + int slashIndex = category.indexOf('/'); + String rootCategory = slashIndex < 0 ? category : category.substring(0, slashIndex); String expandedCategory = getExpandedCategory().getValue(); if (expandedCategory != null && !expandedCategory.equals(rootCategory)) { postExpandedCategory(null); @@ -166,10 +174,22 @@ public class MainViewModel extends AndroidViewModel { @NonNull @MainThread - public LiveData<android.util.Pair<NavigationCategory, CategorySortingMethod>> getCategorySortingMethodOfSelectedCategory() { + public LiveData<Pair<NavigationCategory, CategorySortingMethod>> getCategorySortingMethodOfSelectedCategory() { return switchMap(getSelectedCategory(), selectedCategory -> map(db.getCategoryOrder(selectedCategory), sortingMethod -> new Pair<>(selectedCategory, sortingMethod))); } + public LiveData<Void> modifyCategoryOrder(@NonNull NavigationCategory selectedCategory, @NonNull CategorySortingMethod sortingMethod) { + return switchMap(getCurrentAccount(), currentAccount -> { + if (currentAccount == null) { + return new MutableLiveData<>(null); + } else { + Log.v(TAG, "[modifyCategoryOrder] - currentAccount: " + currentAccount.getAccountName()); + db.modifyCategoryOrder(currentAccount.getId(), selectedCategory, sortingMethod); + return new MutableLiveData<>(null); + } + }); + } + public void postExpandedCategory(@Nullable String expandedCategory) { state.set(KEY_EXPANDED_CATEGORY, expandedCategory); this.expandedCategory.postValue(expandedCategory); @@ -193,13 +213,14 @@ public class MainViewModel extends AndroidViewModel { if (selectedCategory == null) { return insufficientInformation; } else { + Log.v(TAG, "[getNotesListLiveData] - selectedCategory: " + selectedCategory); return switchMap(getSearchTerm(), searchTerm -> { Log.v(TAG, "[getNotesListLiveData] - searchTerm: " + searchTerm); return switchMap(getCategorySortingMethodOfSelectedCategory(), sortingMethod -> { final long accountId = currentAccount.getId(); final String searchQueryOrWildcard = searchTerm == null ? "%" : "%" + searchTerm.trim() + "%"; Log.v(TAG, "[getNotesListLiveData] - sortMethod: " + sortingMethod.second); - final LiveData<List<NoteWithCategory>> fromDatabase; + final LiveData<List<Note>> fromDatabase; switch (selectedCategory.getType()) { case RECENT: { Log.v(TAG, "[getNotesListLiveData] - category: " + RECENT); @@ -224,20 +245,20 @@ public class MainViewModel extends AndroidViewModel { } case DEFAULT_CATEGORY: default: { - final Category category = selectedCategory.getCategory(); + final String category = selectedCategory.getCategory(); if (category == null) { throw new IllegalStateException(NavigationCategory.class.getSimpleName() + " type is " + DEFAULT_CATEGORY + ", but category is null."); } - Log.v(TAG, "[getNotesListLiveData] - category: " + category.getTitle()); + Log.v(TAG, "[getNotesListLiveData] - category: " + category); fromDatabase = sortingMethod.second == SORT_MODIFIED_DESC - ? db.getNoteDao().searchCategoryByModified(accountId, searchQueryOrWildcard, category.getTitle()) - : db.getNoteDao().searchCategoryLexicographically(accountId, searchQueryOrWildcard, category.getTitle()); + ? db.getNoteDao().searchCategoryByModified(accountId, searchQueryOrWildcard, category) + : db.getNoteDao().searchCategoryLexicographically(accountId, searchQueryOrWildcard, category); break; } } Log.v(TAG, "[getNotesListLiveData] - -------------------------------------"); - return distinctUntilChanged(map(fromDatabase, noteList -> fromNotesWithCategory(noteList, selectedCategory, sortingMethod.second))); + return distinctUntilChanged(map(fromDatabase, noteList -> fromNotes(noteList, selectedCategory, sortingMethod.second))); }); }); } @@ -246,11 +267,11 @@ public class MainViewModel extends AndroidViewModel { })); } - private List<Item> fromNotesWithCategory(List<NoteWithCategory> noteList, @NonNull NavigationCategory selectedCategory, @Nullable CategorySortingMethod sortingMethod) { + private List<Item> fromNotes(List<Note> noteList, @NonNull NavigationCategory selectedCategory, @Nullable CategorySortingMethod sortingMethod) { if (selectedCategory.getType() == DEFAULT_CATEGORY) { - final Category category = selectedCategory.getCategory(); + final String category = selectedCategory.getCategory(); if (category != null) { - return fillListByCategory(noteList, category.getTitle()); + return fillListByCategory(noteList, category); } else { throw new IllegalStateException(NavigationCategory.class.getSimpleName() + " type is " + DEFAULT_CATEGORY + ", but category is null."); } @@ -273,7 +294,7 @@ public class MainViewModel extends AndroidViewModel { Log.v(TAG, "[getNavigationCategories] - currentAccount: " + currentAccount.getAccountName()); return switchMap(getExpandedCategory(), expandedCategory -> { Log.v(TAG, "[getNavigationCategories] - expandedCategory: " + expandedCategory); - return distinctUntilChanged(map(db.getCategoryDao().getCategoriesLiveData(currentAccount.getId()), fromDatabase -> + return distinctUntilChanged(map(db.getNoteDao().getCategoriesLiveData(currentAccount.getId()), fromDatabase -> fromCategoriesWithNotesCount(getApplication(), expandedCategory, fromDatabase, db.getNoteDao().count(currentAccount.getId()), db.getNoteDao().getFavoritesCount(currentAccount.getId())) )); }); @@ -342,18 +363,6 @@ public class MainViewModel extends AndroidViewModel { return items; } - public LiveData<Void> modifyCategoryOrder(@NonNull NavigationCategory selectedCategory, @NonNull CategorySortingMethod sortingMethod) { - return switchMap(getCurrentAccount(), currentAccount -> { - if (currentAccount == null) { - return new MutableLiveData<>(null); - } else { - Log.v(TAG, "[modifyCategoryOrder] - currentAccount: " + currentAccount.getAccountName()); - db.modifyCategoryOrder(currentAccount.getId(), selectedCategory, sortingMethod); - return new MutableLiveData<>(null); - } - }); - } - /** * @return <code>true</code>, if a synchronization could successfully be triggered, <code>false</code> if not. */ @@ -402,7 +411,7 @@ public class MainViewModel extends AndroidViewModel { return insufficientInformation; } else { Log.i(TAG, "[performFullSynchronizationForCurrentAccount] Refreshing capabilities for " + localAccount.getAccountName()); - MutableLiveData<Boolean> syncCapabilitiesLiveData = new MutableLiveData<>(); + final MutableLiveData<Boolean> syncCapabilitiesLiveData = new MutableLiveData<>(); new Thread(() -> { final Capabilities capabilities; try { @@ -430,7 +439,7 @@ public class MainViewModel extends AndroidViewModel { } }).start(); - return switchMap(syncCapabilitiesLiveData, (Function<Boolean, LiveData<Boolean>>) capabilitiesSyncedSuccessfully -> { + return switchMap(syncCapabilitiesLiveData, capabilitiesSyncedSuccessfully -> { if (Boolean.TRUE.equals(capabilitiesSyncedSuccessfully)) { Log.v(TAG, "[performFullSynchronizationForCurrentAccount] Capabilities refreshed successfully - synchronize notes for " + localAccount.getAccountName()); return synchronize(); @@ -467,13 +476,8 @@ public class MainViewModel extends AndroidViewModel { }); } - public LiveData<NoteWithCategory> moveNoteToAnotherAccount(Account account, Long noteId) { - return db.moveNoteToAnotherAccount(account, db.getNoteDao().getFullNoteWithCategory(noteId)); - } - - @WorkerThread - public Category getCategory(long id) { - return db.getCategoryDao().getCategory(id); + public LiveData<Note> moveNoteToAnotherAccount(Account account, Long noteId) { + return db.moveNoteToAnotherAccount(account, db.getNoteDao().getNoteById(noteId)); } public LiveData<Void> toggleFavoriteAndSync(long noteId) { @@ -518,21 +522,21 @@ public class MainViewModel extends AndroidViewModel { return db.addAccount(url, username, accountName, capabilities); } - public LiveData<NoteWithCategory> getFullNoteWithCategory(long id) { + public LiveData<Note> getFullNote(long id) { return map(getFullNotesWithCategory(Collections.singleton(id)), input -> input.get(0)); } - public LiveData<List<NoteWithCategory>> getFullNotesWithCategory(@NonNull Collection<Long> ids) { + public LiveData<List<Note>> getFullNotesWithCategory(@NonNull Collection<Long> ids) { return switchMap(getCurrentAccount(), currentAccount -> { if (currentAccount == null) { return new MutableLiveData<>(); } else { - Log.v(TAG, "[getNoteWithCategory] - currentAccount: " + currentAccount.getAccountName()); - final MutableLiveData<List<NoteWithCategory>> notes = new MutableLiveData<>(); + Log.v(TAG, "[getNote] - currentAccount: " + currentAccount.getAccountName()); + final MutableLiveData<List<Note>> notes = new MutableLiveData<>(); new Thread(() -> notes.postValue( ids .stream() - .map(id -> db.getNoteDao().getFullNoteWithCategory(id)) + .map(id -> db.getNoteDao().getNoteById(id)) .collect(Collectors.toList()) )).start(); return notes; @@ -540,7 +544,7 @@ public class MainViewModel extends AndroidViewModel { }); } - public LiveData<NoteWithCategory> addNoteAndSync(NoteWithCategory note) { + public LiveData<Note> addNoteAndSync(Note note) { return switchMap(getCurrentAccount(), currentAccount -> { if (currentAccount == null) { return new MutableLiveData<>(); @@ -551,7 +555,7 @@ public class MainViewModel extends AndroidViewModel { }); } - public LiveData<Void> updateNoteAndSync(@NonNull NoteWithCategory oldNote, @Nullable String newContent, @Nullable String newTitle) { + public LiveData<Void> updateNoteAndSync(@NonNull Note oldNote, @Nullable String newContent, @Nullable String newTitle) { return switchMap(getCurrentAccount(), currentAccount -> { if (currentAccount != null) { Log.v(TAG, "[updateNoteAndSync] - currentAccount: " + currentAccount.getAccountName()); @@ -577,7 +581,7 @@ public class MainViewModel extends AndroidViewModel { new Thread(() -> { final StringBuilder noteContents = new StringBuilder(); for (Long noteId : noteIds) { - final NoteWithCategory fullNote = db.getNoteDao().getFullNoteWithCategory(noteId); + final Note fullNote = db.getNoteDao().getNoteById(noteId); final String tempFullNote = fullNote.getContent(); if (!TextUtils.isEmpty(tempFullNote)) { if (noteContents.length() > 0) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/MultiSelectedActionModeCallback.java b/app/src/main/java/it/niedermann/owncloud/notes/main/MultiSelectedActionModeCallback.java index 6d5806e5..97c18e0c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/MultiSelectedActionModeCallback.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/MultiSelectedActionModeCallback.java @@ -11,28 +11,23 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.appcompat.view.ActionMode; import androidx.appcompat.view.ActionMode.Callback; -import androidx.appcompat.widget.SearchView; import androidx.core.graphics.drawable.DrawableCompat; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LiveData; import androidx.recyclerview.selection.SelectionTracker; -import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.snackbar.Snackbar; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.accountpicker.AccountPickerDialogFragment; import it.niedermann.owncloud.notes.branding.BrandedSnackbar; import it.niedermann.owncloud.notes.edit.category.CategoryDialogFragment; -import it.niedermann.owncloud.notes.main.items.ItemAdapter; import it.niedermann.owncloud.notes.persistence.entity.Account; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.util.ShareUtil; public class MultiSelectedActionModeCallback implements Callback { @@ -102,7 +97,7 @@ public class MultiSelectedActionModeCallback implements Callback { for(Long sel : tracker.getSelection()) { selection.add(sel); } - final LiveData<List<NoteWithCategory>> fullNotes$ = mainViewModel.getFullNotesWithCategory(selection); + final LiveData<List<Note>> fullNotes$ = mainViewModel.getFullNotesWithCategory(selection); fullNotes$.observe(lifecycleOwner, (fullNotes) -> { fullNotes$.removeObservers(lifecycleOwner); tracker.clearSelection(); @@ -113,8 +108,8 @@ public class MultiSelectedActionModeCallback implements Callback { : context.getResources().getQuantityString(R.plurals.bulk_notes_deleted, fullNotes.size(), fullNotes.size()); BrandedSnackbar.make(view, deletedSnackbarTitle, Snackbar.LENGTH_LONG) .setAction(R.string.action_undo, (View v) -> { - for (NoteWithCategory deletedNote : fullNotes) { - final LiveData<NoteWithCategory> undoLiveData = mainViewModel.addNoteAndSync(deletedNote); + for (Note deletedNote : fullNotes) { + final LiveData<Note> undoLiveData = mainViewModel.addNoteAndSync(deletedNote); undoLiveData.observe(lifecycleOwner, (o) -> undoLiveData.removeObservers(lifecycleOwner)); } String restoreSnackbarTitle = fullNotes.size() == 1 @@ -143,7 +138,7 @@ public class MultiSelectedActionModeCallback implements Callback { // FIXME use title if only one final String subject = context.getResources().getQuantityString(R.plurals.share_multiple, selection.size(), selection.size()); // final String subject = (selection.size() == 1) -// ? ((NoteWithCategory) adapter.getItem(adapter.getSelected().get(0))).getTitle() +// ? ((Note) adapter.getItem(adapter.getSelected().get(0))).getTitle() // : context.getResources().getQuantityString(R.plurals.share_multiple, adapter.getSelected().size(), adapter.getSelected().size()); final LiveData<String> contentCollector = mainViewModel.collectNoteContents(selection); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/ItemAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/ItemAdapter.java index 517996e0..88c88b8e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/ItemAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/ItemAdapter.java @@ -32,7 +32,7 @@ import it.niedermann.owncloud.notes.main.items.list.NoteViewHolderWithExcerpt; import it.niedermann.owncloud.notes.main.items.list.NoteViewHolderWithoutExcerpt; import it.niedermann.owncloud.notes.main.items.section.SectionItem; import it.niedermann.owncloud.notes.main.items.section.SectionViewHolder; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.model.Item; import it.niedermann.owncloud.notes.shared.model.NoteClickListener; @@ -81,7 +81,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i public long getItemId(int position) { return getItemViewType(position) == TYPE_SECTION ? ((SectionItem) getItem(position)).getTitle().hashCode() * -1 - : ((NoteWithCategory) getItem(position)).getId(); + : ((Note) getItem(position)).getId(); } /** @@ -155,7 +155,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i case TYPE_NOTE_WITH_EXCERPT: case TYPE_NOTE_WITHOUT_EXCERPT: case TYPE_NOTE_ONLY_TITLE: { - ((NoteViewHolder) holder).bind(isSelected, (NoteWithCategory) itemList.get(position), showCategory, mainColor, textColor, searchQuery); + ((NoteViewHolder) holder).bind(isSelected, (Note) itemList.get(position), showCategory, mainColor, textColor, searchQuery); break; } } @@ -191,7 +191,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i throw new IllegalArgumentException("Item at position " + position + " must not be null"); } if (getItem(position).isSection()) return TYPE_SECTION; - NoteWithCategory note = (NoteWithCategory) getItem(position); + Note note = (Note) getItem(position); if (TextUtils.isEmpty(note.getExcerpt())) { if (TextUtils.isEmpty(note.getCategory())) { return TYPE_NOTE_ONLY_TITLE; diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/NoteViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/NoteViewHolder.java index 24153135..cdc18e3c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/NoteViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/NoteViewHolder.java @@ -31,7 +31,7 @@ import it.niedermann.android.util.ColorUtil; import it.niedermann.owncloud.notes.NotesApplication; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.BrandingUtil; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.NoteClickListener; @@ -50,7 +50,7 @@ public abstract class NoteViewHolder extends RecyclerView.ViewHolder { } @CallSuper - public void bind(boolean isSelected, @NonNull NoteWithCategory note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + public void bind(boolean isSelected, @NonNull Note note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { itemView.setSelected(isSelected); itemView.setOnClickListener((view) -> noteClickListener.onNoteClick(getLayoutPosition(), view)); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolder.java index ab772af3..7c4cecfe 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolder.java @@ -13,7 +13,6 @@ import androidx.annotation.Px; import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemGridBinding; import it.niedermann.owncloud.notes.main.items.NoteViewHolder; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.NoteClickListener; import static android.view.View.GONE; @@ -40,11 +39,10 @@ public class NoteViewGridHolder extends NoteViewHolder { throw new UnsupportedOperationException(NoteViewGridHolder.class.getSimpleName() + " does not support swiping"); } - public void bind(boolean isSelected, @NonNull NoteWithCategory noteWithCategory, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { - super.bind(isSelected, noteWithCategory, showCategory, mainColor, textColor, searchQuery); - Note note = noteWithCategory.getNote(); + public void bind(boolean isSelected, @NonNull Note note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + super.bind(isSelected, note, showCategory, mainColor, textColor, searchQuery); @NonNull final Context context = itemView.getContext(); - bindCategory(context, binding.noteCategory, showCategory, noteWithCategory.getCategory(), mainColor); + bindCategory(context, binding.noteCategory, showCategory, note.getCategory(), mainColor); bindStatus(binding.noteStatus, note.getStatus(), mainColor); bindFavorite(binding.noteFavorite, note.getFavorite()); bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolderOnlyTitle.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolderOnlyTitle.java index c99a96e7..416d99d2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolderOnlyTitle.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/NoteViewGridHolderOnlyTitle.java @@ -11,7 +11,7 @@ import androidx.annotation.Px; import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemGridOnlyTitleBinding; import it.niedermann.owncloud.notes.main.items.NoteViewHolder; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.model.NoteClickListener; public class NoteViewGridHolderOnlyTitle extends NoteViewHolder { @@ -32,7 +32,7 @@ public class NoteViewGridHolderOnlyTitle extends NoteViewHolder { throw new UnsupportedOperationException(NoteViewGridHolderOnlyTitle.class.getSimpleName() + " does not support swiping"); } - public void bind(boolean isSelected, @NonNull NoteWithCategory note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + public void bind(boolean isSelected, @NonNull Note note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { super.bind(isSelected, note, showCategory, mainColor, textColor, searchQuery); @NonNull final Context context = itemView.getContext(); bindStatus(binding.noteStatus, note.getStatus(), mainColor); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithExcerpt.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithExcerpt.java index 4b644160..8d1cfe07 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithExcerpt.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithExcerpt.java @@ -10,7 +10,6 @@ import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithExcerptBinding; import it.niedermann.owncloud.notes.main.items.NoteViewHolder; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.NoteClickListener; @@ -29,12 +28,11 @@ public class NoteViewHolderWithExcerpt extends NoteViewHolder { binding.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention); } - public void bind(boolean isSelected, @NonNull NoteWithCategory noteWithCategory, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { - super.bind(isSelected, noteWithCategory, showCategory, mainColor, textColor, searchQuery); - Note note = noteWithCategory.getNote(); + public void bind(boolean isSelected, @NonNull Note note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + super.bind(isSelected, note, showCategory, mainColor, textColor, searchQuery); @NonNull final Context context = itemView.getContext(); binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); - bindCategory(context, binding.noteCategory, showCategory, noteWithCategory.getCategory(), mainColor); + bindCategory(context, binding.noteCategory, showCategory, note.getCategory(), mainColor); bindStatus(binding.noteStatus, note.getStatus(), mainColor); bindFavorite(binding.noteFavorite, note.getFavorite()); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithoutExcerpt.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithoutExcerpt.java index cf74dbd1..3ca136e4 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithoutExcerpt.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NoteViewHolderWithoutExcerpt.java @@ -10,7 +10,6 @@ import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithoutExcerptBinding; import it.niedermann.owncloud.notes.main.items.NoteViewHolder; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.NoteClickListener; @@ -29,12 +28,11 @@ public class NoteViewHolderWithoutExcerpt extends NoteViewHolder { binding.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention); } - public void bind(boolean isSelected, @NonNull NoteWithCategory noteWithCategory, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { - super.bind(isSelected, noteWithCategory, showCategory, mainColor, textColor, searchQuery); - Note note = noteWithCategory.getNote(); + public void bind(boolean isSelected, @NonNull Note note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + super.bind(isSelected, note, showCategory, mainColor, textColor, searchQuery); @NonNull final Context context = itemView.getContext(); binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); - bindCategory(context, binding.noteCategory, showCategory, noteWithCategory.getCategory(), mainColor); + bindCategory(context, binding.noteCategory, showCategory, note.getCategory(), mainColor); bindStatus(binding.noteStatus, note.getStatus(), mainColor); bindFavorite(binding.noteFavorite, note.getFavorite()); bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NotesListViewItemTouchHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NotesListViewItemTouchHelper.java index f98f5b83..19a7b74d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NotesListViewItemTouchHelper.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/list/NotesListViewItemTouchHelper.java @@ -23,7 +23,7 @@ import it.niedermann.owncloud.notes.main.MainViewModel; import it.niedermann.owncloud.notes.main.items.ItemAdapter; import it.niedermann.owncloud.notes.main.items.NoteViewHolder; import it.niedermann.owncloud.notes.main.items.section.SectionViewHolder; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; public class NotesListViewItemTouchHelper extends ItemTouchHelper { @@ -72,8 +72,8 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper { switch (direction) { case ItemTouchHelper.LEFT: viewHolder.setIsRecyclable(false); - final NoteWithCategory dbNoteWithoutContent = (NoteWithCategory) adapter.getItem(viewHolder.getLayoutPosition()); - final LiveData<NoteWithCategory> dbNoteLiveData = mainViewModel.getFullNoteWithCategory(dbNoteWithoutContent.getId()); + final Note dbNoteWithoutContent = (Note) adapter.getItem(viewHolder.getLayoutPosition()); + final LiveData<Note> dbNoteLiveData = mainViewModel.getFullNote(dbNoteWithoutContent.getId()); dbNoteLiveData.observe(lifecycleOwner, (dbNote) -> { dbNoteLiveData.removeObservers(lifecycleOwner); tracker.deselect(dbNote.getId()); @@ -82,7 +82,7 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper { Log.v(TAG, "Item deleted through swipe ----------------------------------------------"); BrandedSnackbar.make(view, context.getString(R.string.action_note_deleted, dbNote.getTitle()), UNDO_DURATION) .setAction(R.string.action_undo, (View v) -> { - final LiveData<NoteWithCategory> undoLiveData = mainViewModel.addNoteAndSync(dbNote); + final LiveData<Note> undoLiveData = mainViewModel.addNoteAndSync(dbNote); undoLiveData.observe(lifecycleOwner, (o) -> undoLiveData.removeObservers(lifecycleOwner)); BrandedSnackbar.make(view, context.getString(R.string.action_note_restored, dbNote.getTitle()), Snackbar.LENGTH_SHORT) .show(); @@ -92,7 +92,7 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper { break; case ItemTouchHelper.RIGHT: viewHolder.setIsRecyclable(false); - final NoteWithCategory adapterNote = (NoteWithCategory) adapter.getItem(viewHolder.getLayoutPosition()); + final Note adapterNote = (Note) adapter.getItem(viewHolder.getLayoutPosition()); final LiveData<Void> toggleLiveData = mainViewModel.toggleFavoriteAndSync(adapterNote.getId()); toggleLiveData.observe(lifecycleOwner, (next) -> toggleLiveData.removeObservers(lifecycleOwner)); break; diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/navigation/NavigationItem.java b/app/src/main/java/it/niedermann/owncloud/notes/main/navigation/NavigationItem.java index c0690dc6..25ea4abb 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/navigation/NavigationItem.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/navigation/NavigationItem.java @@ -39,12 +39,14 @@ public class NavigationItem { } public static class CategoryNavigationItem extends NavigationItem { + public long accountId; @NonNull - public Long categoryId; + public String category; - public CategoryNavigationItem(@NonNull String id, @NonNull String label, @Nullable Integer count, @DrawableRes int icon, @NonNull Long categoryId) { + public CategoryNavigationItem(@NonNull String id, @NonNull String label, @Nullable Integer count, @DrawableRes int icon, long accountId, @NonNull String category) { super(id, label, count, icon, ENavigationCategoryType.DEFAULT_CATEGORY); - this.categoryId = categoryId; + this.accountId = accountId; + this.category = category; } @Override @@ -55,13 +57,15 @@ public class NavigationItem { CategoryNavigationItem that = (CategoryNavigationItem) o; - return categoryId.equals(that.categoryId); + if (accountId != that.accountId) return false; + return category.equals(that.category); } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + categoryId.hashCode(); + result = 31 * result + (int) (accountId ^ (accountId >>> 32)); + result = 31 * result + category.hashCode(); return result; } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/slots/SlotterUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/main/slots/SlotterUtil.java index cc4b6afe..206ee9ca 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/slots/SlotterUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/slots/SlotterUtil.java @@ -10,7 +10,7 @@ import java.util.List; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.main.items.section.SectionItem; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.model.Item; import it.niedermann.owncloud.notes.shared.util.NoteUtil; @@ -21,9 +21,9 @@ public class SlotterUtil { } @NonNull - public static List<Item> fillListByCategory(@NonNull List<NoteWithCategory> noteList, @Nullable String currentCategory) { + public static List<Item> fillListByCategory(@NonNull List<Note> noteList, @Nullable String currentCategory) { List<Item> itemList = new ArrayList<>(); - for (NoteWithCategory note : noteList) { + for (Note note : noteList) { if (currentCategory != null && !currentCategory.equals(note.getCategory())) { itemList.add(new SectionItem(NoteUtil.extendCategory(note.getCategory()))); } @@ -35,13 +35,13 @@ public class SlotterUtil { } @NonNull - public static List<Item> fillListByTime(@NonNull Context context, @NonNull List<NoteWithCategory> noteList) { + public static List<Item> fillListByTime(@NonNull Context context, @NonNull List<Note> noteList) { List<Item> itemList = new ArrayList<>(); Timeslotter timeslotter = new Timeslotter(context); String lastTimeslot = null; for (int i = 0; i < noteList.size(); i++) { - NoteWithCategory currentNote = noteList.get(i); - String timeslot = timeslotter.getTimeslot(currentNote.getNote()); + Note currentNote = noteList.get(i); + String timeslot = timeslotter.getTimeslot(currentNote); if (i > 0 && !timeslot.equals(lastTimeslot)) { itemList.add(new SectionItem(timeslot)); } @@ -53,11 +53,11 @@ public class SlotterUtil { } @NonNull - public static List<Item> fillListByInitials(@NonNull Context context, @NonNull List<NoteWithCategory> noteList) { + public static List<Item> fillListByInitials(@NonNull Context context, @NonNull List<Note> noteList) { List<Item> itemList = new ArrayList<>(); String lastInitials = null; for (int i = 0; i < noteList.size(); i++) { - NoteWithCategory currentNote = noteList.get(i); + Note currentNote = noteList.get(i); String initials = currentNote.getTitle().substring(0, 1).toUpperCase(); if (!initials.matches("[A-Z\\u00C0-\\u00DF]")) { initials = initials.matches("[\\u0250-\\uFFFF]") ? context.getString(R.string.simple_other) : "#"; diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java index 9cc0f25e..d874c1d4 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java @@ -35,7 +35,7 @@ import java.util.Set; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.persistence.entity.Account; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.model.ServerResponse; @@ -43,6 +43,8 @@ import it.niedermann.owncloud.notes.shared.model.SyncResultStatus; import it.niedermann.owncloud.notes.shared.util.SSOUtil; import static androidx.lifecycle.Transformations.distinctUntilChanged; +import static it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED; +import static it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_EDITED; import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED; @@ -364,11 +366,11 @@ public class NoteServerSyncHelper { Log.d(TAG, "pushLocalChanges()"); boolean success = true; - List<NoteWithCategory> notes = db.getNoteDao().getLocalModifiedNotes(localAccount.getId()); - for (NoteWithCategory note : notes) { + List<Note> notes = db.getNoteDao().getLocalModifiedNotes(localAccount.getId()); + for (Note note : notes) { Log.d(TAG, " Process Local Note: " + note); try { - NoteWithCategory remoteNote; + Note remoteNote; switch (note.getStatus()) { case LOCAL_EDITED: Log.v(TAG, " ...create/edit"); @@ -391,8 +393,7 @@ public class NoteServerSyncHelper { } // Please note, that db.updateNote() realized an optimistic conflict resolution, which is required for parallel changes of this Note from the UI. // TODO: check if the Rooms implementation does this correctly! - db.getNoteDao().updateIfNotModifiedLocallyDuringSync(note.getId(), remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()), note.getContent(), note.getFavorite(), note.getNote().getCategoryId()); - db.getNoteDao().updateCategory(note.getId(), db.getOrCreateCategoryIdByTitle(localAccount.getId(), remoteNote.getCategory())); + db.getNoteDao().updateIfNotModifiedLocallyDuringSync(note.getId(), remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()), note.getContent(), note.getCategory(), note.getFavorite()); break; case LOCAL_DELETED: if (note.getRemoteId() == null) { @@ -410,7 +411,7 @@ public class NoteServerSyncHelper { } } // Please note, that db.deleteNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI. - db.getNoteDao().deleteByNoteId(note.getId(), DBStatus.LOCAL_DELETED); + db.getNoteDao().deleteByNoteId(note.getId(), LOCAL_DELETED); break; default: throw new IllegalStateException("Unknown State of Note " + note + ": " + note.getStatus()); @@ -441,10 +442,10 @@ public class NoteServerSyncHelper { try { final Map<Long, Long> idMap = db.getIdMap(localAccount.getId()); final ServerResponse.NotesResponse response = notesClient.getNotes(ssoAccount, localAccount.getModified().getTimeInMillis()/1000, localAccount.getETag()); - List<NoteWithCategory> remoteNotes = response.getNotes(); + List<Note> remoteNotes = response.getNotes(); Set<Long> remoteIDs = new HashSet<>(); // pull remote changes: update or create each remote note - for (NoteWithCategory remoteNote : remoteNotes) { + for (Note remoteNote : remoteNotes) { Log.v(TAG, " Process Remote Note: " + remoteNote); remoteIDs.add(remoteNote.getRemoteId()); if (remoteNote.getModified() == null) { @@ -455,7 +456,6 @@ public class NoteServerSyncHelper { if (localId != null) { db.getNoteDao().updateIfNotModifiedLocallyAndRemoteColumnHasChanged( localId, remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getCategory(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle())); - db.getNoteDao().updateCategory(localId, db.getOrCreateCategoryIdByTitle(localAccount.getId(), remoteNote.getCategory())); } else { Log.e(TAG, "Tried to update note from server, but local id of note is null. " + remoteNote); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java index 2035d5d9..07048ec9 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java @@ -26,7 +26,6 @@ import java.util.Map; import java.util.Objects; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.ApiVersion; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NoteResponse; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NotesResponse; @@ -99,9 +98,9 @@ public abstract class NotesClient { */ abstract NotesResponse getNotes(SingleSignOnAccount ssoAccount, long lastModified, String lastETag) throws Exception; - abstract NoteResponse createNote(SingleSignOnAccount ssoAccount, NoteWithCategory note) throws Exception; + abstract NoteResponse createNote(SingleSignOnAccount ssoAccount, Note note) throws Exception; - abstract NoteResponse editNote(SingleSignOnAccount ssoAccount, NoteWithCategory note) throws Exception; + abstract NoteResponse editNote(SingleSignOnAccount ssoAccount, Note note) throws Exception; abstract void deleteNote(SingleSignOnAccount ssoAccount, long noteId) throws Exception; diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV02.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV02.java index d54d554b..8e6743d9 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV02.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV02.java @@ -13,7 +13,6 @@ import java.util.HashMap; import java.util.Map; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NoteResponse; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NotesResponse; @@ -32,7 +31,7 @@ public class NotesClientV02 extends NotesClient { return new NotesResponse(requestServer(ssoAccount, "notes", METHOD_GET, parameter, null, lastETag)); } - private NoteResponse putNote(SingleSignOnAccount ssoAccount, NoteWithCategory note, String path, String method) throws Exception { + private NoteResponse putNote(SingleSignOnAccount ssoAccount, Note note, String path, String method) throws Exception { JSONObject paramObject = new JSONObject(); paramObject.accumulate(JSON_CONTENT, note.getContent()); paramObject.accumulate(JSON_MODIFIED, note.getModified().getTimeInMillis() / 1000); @@ -42,12 +41,12 @@ public class NotesClientV02 extends NotesClient { } @Override - NoteResponse createNote(SingleSignOnAccount ssoAccount, NoteWithCategory note) throws Exception { + NoteResponse createNote(SingleSignOnAccount ssoAccount, Note note) throws Exception { return putNote(ssoAccount, note, "notes", METHOD_POST); } @Override - NoteResponse editNote(SingleSignOnAccount ssoAccount, NoteWithCategory note) throws Exception { + NoteResponse editNote(SingleSignOnAccount ssoAccount, Note note) throws Exception { return putNote(ssoAccount, note, "notes/" + note.getRemoteId(), METHOD_PUT); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java index 94c17ee6..1094b559 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java @@ -13,7 +13,6 @@ import java.util.HashMap; import java.util.Map; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NoteResponse; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NotesResponse; @@ -32,7 +31,7 @@ public class NotesClientV1 extends NotesClient { return new NotesResponse(requestServer(ssoAccount, "notes", METHOD_GET, parameter, null, lastETag)); } - private NoteResponse putNote(SingleSignOnAccount ssoAccount, NoteWithCategory note, String path, String method) throws Exception { + private NoteResponse putNote(SingleSignOnAccount ssoAccount, Note note, String path, String method) throws Exception { JSONObject paramObject = new JSONObject(); paramObject.accumulate(JSON_TITLE, note.getTitle()); paramObject.accumulate(JSON_CONTENT, note.getContent()); @@ -43,12 +42,12 @@ public class NotesClientV1 extends NotesClient { } @Override - NoteResponse createNote(SingleSignOnAccount ssoAccount, NoteWithCategory note) throws Exception { + NoteResponse createNote(SingleSignOnAccount ssoAccount, Note note) throws Exception { return putNote(ssoAccount, note, "notes", METHOD_POST); } @Override - NoteResponse editNote(SingleSignOnAccount ssoAccount, NoteWithCategory note) throws Exception { + NoteResponse editNote(SingleSignOnAccount ssoAccount, Note note) throws Exception { return putNote(ssoAccount, note, "notes/" + note.getRemoteId(), METHOD_PUT); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java index df396b16..1e239c19 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java @@ -40,15 +40,14 @@ import it.niedermann.android.sharedpreferences.SharedPreferenceIntLiveData; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.edit.EditNoteActivity; import it.niedermann.owncloud.notes.persistence.dao.AccountDao; -import it.niedermann.owncloud.notes.persistence.dao.CategoryDao; +import it.niedermann.owncloud.notes.persistence.dao.CategoryOptionsDao; import it.niedermann.owncloud.notes.persistence.dao.NoteDao; import it.niedermann.owncloud.notes.persistence.dao.WidgetNotesListDao; import it.niedermann.owncloud.notes.persistence.dao.WidgetSingleNoteDao; import it.niedermann.owncloud.notes.persistence.entity.Account; -import it.niedermann.owncloud.notes.persistence.entity.Category; +import it.niedermann.owncloud.notes.persistence.entity.CategoryOptions; import it.niedermann.owncloud.notes.persistence.entity.Converters; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData; import it.niedermann.owncloud.notes.persistence.entity.SingleNoteWidgetData; import it.niedermann.owncloud.notes.persistence.migration.Migration_10_11; @@ -83,7 +82,7 @@ import static it.niedermann.owncloud.notes.widget.singlenote.SingleNoteWidget.up entities = { Account.class, Note.class, - Category.class, + CategoryOptions.class, SingleNoteWidgetData.class, NotesListWidgetData.class }, version = 20 @@ -121,8 +120,9 @@ public abstract class NotesDatabase extends RoomDatabase { @Override public void onCreate(@NonNull SupportSQLiteDatabase db) { super.onCreate(db); - db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_DEL AFTER DELETE ON Note BEGIN DELETE FROM Category WHERE Category.id NOT IN (SELECT Note.categoryId FROM Note); END;"); - db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_UPD AFTER UPDATE ON Note BEGIN DELETE FROM Category WHERE Category.id NOT IN (SELECT Note.categoryId FROM Note); END;"); + final String cleanUpStatement = "DELETE FROM CategoryOptions WHERE CategoryOptions.category NOT IN (SELECT Note.category FROM Note WHERE Note.accountId = CategoryOptions.accountId);"; + db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_DEL AFTER DELETE ON Note BEGIN " + cleanUpStatement + " END;"); + db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_UPD AFTER UPDATE ON Note BEGIN " + cleanUpStatement + " END;"); Log.v(TAG, NotesDatabase.class.getSimpleName() + " created."); } }) @@ -132,7 +132,7 @@ public abstract class NotesDatabase extends RoomDatabase { public abstract AccountDao getAccountDao(); - public abstract CategoryDao getCategoryDao(); + public abstract CategoryOptionsDao getCategoryOptionsDao(); public abstract NoteDao getNoteDao(); @@ -160,14 +160,14 @@ public abstract class NotesDatabase extends RoomDatabase { */ @NonNull @MainThread - public LiveData<NoteWithCategory> addNoteAndSync(Account account, NoteWithCategory note) { - NoteWithCategory entity = new NoteWithCategory(new Note(0, null, note.getModified(), note.getTitle(), note.getContent(), note.getFavorite(), note.getETag(), DBStatus.LOCAL_EDITED, account.getId(), generateNoteExcerpt(note.getContent(), note.getTitle()), 0), note.getCategory()); - final MutableLiveData<NoteWithCategory> ret = new MutableLiveData<>(); + public LiveData<Note> addNoteAndSync(Account account, Note note) { + Note entity = new Note(0, null, note.getModified(), note.getTitle(), note.getContent(), note.getCategory(), note.getFavorite(), note.getETag(), DBStatus.LOCAL_EDITED, account.getId(), generateNoteExcerpt(note.getContent(), note.getTitle()), 0); + final MutableLiveData<Note> ret = new MutableLiveData<>(); new Thread(() -> ret.postValue(addNote(account.getId(), entity))).start(); - return map(ret, newNoteWithCategory -> { + return map(ret, newNote -> { notifyWidgets(); serverSyncHelper.scheduleSync(account, true); - return newNoteWithCategory; + return newNote; }); } @@ -179,7 +179,7 @@ public abstract class NotesDatabase extends RoomDatabase { */ @NonNull @WorkerThread - NoteWithCategory addNote(long accountId, NoteWithCategory note) { + Note addNote(long accountId, Note note) { Note entity = new Note(); if (note.getId() > 0) { entity.setId(note.getId()); @@ -196,16 +196,16 @@ public abstract class NotesDatabase extends RoomDatabase { entity.setModified(note.getModified()); entity.setContent(note.getContent()); entity.setFavorite(note.getFavorite()); - entity.setCategoryId(getOrCreateCategoryIdByTitle(accountId, note.getCategory())); + entity.setCategory(note.getCategory()); entity.setETag(note.getETag()); - return getNoteDao().getFullNoteWithCategory(getNoteDao().addNote(entity)); + return getNoteDao().getNoteById(getNoteDao().addNote(entity)); } @AnyThread - public LiveData<NoteWithCategory> moveNoteToAnotherAccount(Account account, NoteWithCategory note) { - NoteWithCategory noteWithCategory = new NoteWithCategory(new Note(null, note.getModified(), note.getTitle(), getNoteDao().getContent(note.getId()), note.getFavorite(), null), note.getCategory()); + public LiveData<Note> moveNoteToAnotherAccount(Account account, Note note) { + Note Note = new Note(null, note.getModified(), note.getTitle(), getNoteDao().getContent(note.getId()), note.getCategory(), note.getFavorite(), null); deleteNoteAndSync(account, note.getId()); - return addNoteAndSync(account, noteWithCategory); + return addNoteAndSync(account, Note); } @NonNull @@ -240,7 +240,7 @@ public abstract class NotesDatabase extends RoomDatabase { public void setCategory(@NonNull Account account, long noteId, @NonNull String category) { new Thread(() -> { getNoteDao().updateStatus(noteId, DBStatus.LOCAL_EDITED); - getNoteDao().updateCategory(noteId, getOrCreateCategoryIdByTitle(account.getId(), category)); + getNoteDao().updateCategory(noteId, category); serverSyncHelper.scheduleSync(account, true); }).start(); } @@ -256,10 +256,10 @@ public abstract class NotesDatabase extends RoomDatabase { * @return changed {@link Note} if differs from database, otherwise the old {@link Note}. */ @WorkerThread - public NoteWithCategory updateNoteAndSync(Account localAccount, @NonNull NoteWithCategory oldNote, @Nullable String newContent, @Nullable String newTitle, @Nullable ISyncCallback callback) { - final NoteWithCategory newNote; + public Note updateNoteAndSync(Account localAccount, @NonNull Note oldNote, @Nullable String newContent, @Nullable String newTitle, @Nullable ISyncCallback callback) { + final Note newNote; if (newContent == null) { - newNote = new NoteWithCategory(new Note(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), oldNote.getExcerpt(), oldNote.getScrollY()), oldNote.getCategory()); + newNote = new Note(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.getCategory(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), oldNote.getExcerpt(), oldNote.getScrollY()); } else { final String title; if (newTitle != null) { @@ -271,10 +271,9 @@ public abstract class NotesDatabase extends RoomDatabase { title = oldNote.getTitle(); } } - newNote = new NoteWithCategory(new Note(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), title, newContent, oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), generateNoteExcerpt(newContent, title), oldNote.getScrollY()), oldNote.getCategory()); + newNote = new Note(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), title, newContent, oldNote.getCategory(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), generateNoteExcerpt(newContent, title), oldNote.getScrollY()); } - newNote.getNote().setCategoryId(getOrCreateCategoryIdByTitle(newNote.getAccountId(), newNote.getCategory())); - int rows = getNoteDao().updateNote(newNote.getNote()); + int rows = getNoteDao().updateNote(newNote); // if data was changed, set new status and schedule sync (with callback); otherwise invoke callback directly. if (rows > 0) { notifyWidgets(); @@ -437,32 +436,6 @@ public abstract class NotesDatabase extends RoomDatabase { return ret; } - /** - * Get the category if with the given category title - * The method does not support fuzzy search. - * Because the category title in database is unique, there will not at most one result. - * If there is no such category, database will create it if create flag is set. - * Otherwise this method will return -1 as default value. - * - * @param accountId The user {@link Account} Id - * @param categoryTitle The category title which will be search in the db - * @return -1 if there is no such category else the corresponding id - */ - @NonNull - @WorkerThread - protected Long getOrCreateCategoryIdByTitle(long accountId, @NonNull String categoryTitle) { - validateAccountId(accountId); - Long categoryId = getCategoryDao().getCategoryIdByTitle(accountId, categoryTitle); - if (categoryId != null && categoryId > 0) { - return categoryId; - } else { - Category entity = new Category(); - entity.setAccountId(accountId); - entity.setTitle(categoryTitle); - return getCategoryDao().addCategory(entity); - } - } - private static void validateAccountId(long accountId) { if (accountId < 1) { throw new IllegalArgumentException("accountId must be greater than 0"); @@ -504,9 +477,16 @@ public abstract class NotesDatabase extends RoomDatabase { } case DEFAULT_CATEGORY: default: { - final Category category = selectedCategory.getCategory(); + final String category = selectedCategory.getCategory(); if (category != null) { - getCategoryDao().modifyCategoryOrder(accountId, category.getId(), sortingMethod); + if(getCategoryOptionsDao().modifyCategoryOrder(accountId, category, sortingMethod) == 0) { + // Nothing updated means we didn't have this yet + final CategoryOptions categoryOptions = new CategoryOptions(); + categoryOptions.setAccountId(accountId); + categoryOptions.setCategory(category); + categoryOptions.setSortingMethod(sortingMethod); + getCategoryOptionsDao().addCategoryOptions(categoryOptions); + } } else { throw new IllegalStateException("Tried to modify category order for " + ENavigationCategoryType.DEFAULT_CATEGORY + "but category is null."); } @@ -519,8 +499,8 @@ public abstract class NotesDatabase extends RoomDatabase { /** * Gets the sorting method of a {@link NavigationCategory}, the category can be normal - * {@link Category} or one of {@link ENavigationCategoryType}. - * If the category no normal {@link Category}, sorting method will be got from + * {@link CategoryOptions} or one of {@link ENavigationCategoryType}. + * If the category no normal {@link CategoryOptions}, sorting method will be got from * {@link SharedPreferences}. * <p> * The sorting method of the category can be used to decide to use which sorting method to show @@ -551,9 +531,9 @@ public abstract class NotesDatabase extends RoomDatabase { } case DEFAULT_CATEGORY: default: { - final Category category = selectedCategory.getCategory(); + final String category = selectedCategory.getCategory(); if (category != null) { - return getCategoryDao().getCategoryOrder(category.getId()); + return getCategoryOptionsDao().getCategoryOrder(selectedCategory.getAccountId(), category); } else { Log.e(TAG, "Cannot read " + CategorySortingMethod.class.getSimpleName() + " for " + ENavigationCategoryType.DEFAULT_CATEGORY + "."); return new MutableLiveData<>(CategorySortingMethod.SORT_MODIFIED_DESC); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/CategoryDao.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/CategoryDao.java deleted file mode 100644 index 8ecd6055..00000000 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/CategoryDao.java +++ /dev/null @@ -1,67 +0,0 @@ -package it.niedermann.owncloud.notes.persistence.dao; - -import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Insert; -import androidx.room.Query; - -import java.util.List; - -import it.niedermann.owncloud.notes.persistence.entity.Category; -import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount; -import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; - -@Dao -public interface CategoryDao { - - @Insert - Long addCategory(Category entity); - - @Query("SELECT * FROM CATEGORY WHERE id = :id") - Category getCategory(long id); - - @Query("SELECT id FROM CATEGORY WHERE accountId = :accountId AND title = :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. - * 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. - * - * @param accountId The user accountID - * @param categoryId The category id - * @param sortingMethod The sorting method in {@link CategorySortingMethod} enum format - */ - @Query("UPDATE CATEGORY SET sortingMethod = :sortingMethod WHERE id = :categoryId AND accountId = :accountId") - void modifyCategoryOrder(long accountId, long categoryId, CategorySortingMethod sortingMethod); - - /** - * 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 - * to use which sorting method to show the notes for each categories. - * - * @param categoryId The category title - * @return The sorting method in {@link CategorySortingMethod} enum format - */ - @Query("SELECT sortingMethod FROM CATEGORY WHERE id = :categoryId") - LiveData<CategorySortingMethod> getCategoryOrder(long categoryId); - - @Query("SELECT title FROM CATEGORY WHERE id = :id") - String getCategoryTitleById(long id); - - /** - * This method return all of the categories with given accountId - * - * @param accountId The user account Id - * @return All of the categories with given accountId - */ - @Query("SELECT CATEGORY.id, CATEGORY.title, COUNT(*) as 'totalNotes' FROM CATEGORY INNER JOIN NOTE ON categoryId = CATEGORY.id WHERE STATUS != 'LOCAL_DELETED' AND CATEGORY.accountId = :accountId GROUP BY CATEGORY.title") - LiveData<List<CategoryWithNotesCount>> getCategoriesLiveData(Long accountId); - - @Query("SELECT CATEGORY.id, CATEGORY.title, COUNT(*) as 'totalNotes' FROM CATEGORY INNER JOIN NOTE ON categoryId = CATEGORY.id WHERE CATEGORY.title != '' AND STATUS != 'LOCAL_DELETED' AND CATEGORY.accountId = :accountId AND CATEGORY.title LIKE :searchTerm GROUP BY CATEGORY.title") - LiveData<List<CategoryWithNotesCount>> searchCategories(Long accountId, String searchTerm); -} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/CategoryOptionsDao.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/CategoryOptionsDao.java new file mode 100644 index 00000000..46fdb0f5 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/CategoryOptionsDao.java @@ -0,0 +1,42 @@ +package it.niedermann.owncloud.notes.persistence.dao; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.Query; + +import java.util.List; + +import it.niedermann.owncloud.notes.persistence.entity.CategoryOptions; +import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount; +import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; + +@Dao +public interface CategoryOptionsDao { + + @Insert + void addCategoryOptions(CategoryOptions entity); + + /** + * This method is used to modify the sorting method for one category by title. + * 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. + * + * @param accountId The user accountID + * @param category The category + * @param sortingMethod The sorting method in {@link CategorySortingMethod} enum format + */ + @Query("UPDATE CategoryOptions SET sortingMethod = :sortingMethod WHERE category = :category AND accountId = :accountId") + int modifyCategoryOrder(long accountId, String category, CategorySortingMethod sortingMethod); + + /** + * 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 + * to use which sorting method to show the notes for each categories. + * + * @param category The category + * @return The sorting method in {@link CategorySortingMethod} enum format + */ + @Query("SELECT sortingMethod FROM CategoryOptions WHERE accountId = :accountId AND category = :category") + LiveData<CategorySortingMethod> getCategoryOrder(long accountId, String category); +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java index 16772074..39d2f328 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java @@ -11,8 +11,8 @@ import java.util.List; import java.util.Set; import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper; +import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.shared.model.DBStatus; @Dao @@ -27,45 +27,29 @@ public interface NoteDao { @Query("DELETE FROM NOTE WHERE accountId = :accountId") int deleteByAccountId(Long accountId); - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, NOTE.title, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) " + - "ORDER BY favorite DESC, NOTE.modified DESC") - LiveData<List<NoteWithCategory>> searchRecentByModified(long accountId, String query); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, NOTE.title, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) " + - "ORDER BY favorite DESC, NOTE.title COLLATE NOCASE ASC") - LiveData<List<NoteWithCategory>> searchRecentLexicographically(long accountId, String query); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, NOTE.title, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) AND favorite = 1 " + - "ORDER BY NOTE.modified DESC") - LiveData<List<NoteWithCategory>> searchFavoritesByModified(long accountId, String query); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, NOTE.title, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) AND favorite = 1 " + - "ORDER BY NOTE.title COLLATE NOCASE ASC") - LiveData<List<NoteWithCategory>> searchFavoritesLexicographically(long accountId, String query); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, NOTE.title, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) AND CATEGORY.title = '' " + - "ORDER BY favorite DESC, NOTE.modified DESC") - LiveData<List<NoteWithCategory>> searchUncategorizedByModified(long accountId, String query); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, NOTE.title, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) AND CATEGORY.title = '' " + - "ORDER BY favorite DESC, NOTE.title COLLATE NOCASE ASC") - LiveData<List<NoteWithCategory>> searchUncategorizedLexicographically(long accountId, String query); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) AND (CATEGORY.title = :category OR CATEGORY.title LIKE :category || '/%') " + - "ORDER BY CATEGORY.title, NOTE.favorite DESC, NOTE.modified DESC") - LiveData<List<NoteWithCategory>> searchCategoryByModified(long accountId, String query, String category); - - @Query("SELECT NOTE.id, NOTE.accountId, NOTE.title, NOTE.excerpt, NOTE.favorite, NOTE.modified, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id " + - "WHERE NOTE.accountId = :accountId AND status != 'LOCAL_DELETED' AND (NOTE.title LIKE :query OR content LIKE :query) AND (CATEGORY.title = :category OR CATEGORY.title LIKE :category || '/%') " + - "ORDER BY CATEGORY.title, NOTE.favorite DESC, NOTE.title COLLATE NOCASE ASC") - LiveData<List<NoteWithCategory>> searchCategoryLexicographically(long accountId, String query, String category); + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, modified DESC") + LiveData<List<Note>> searchRecentByModified(long accountId, String query); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, title COLLATE NOCASE ASC") + LiveData<List<Note>> searchRecentLexicographically(long accountId, String query); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY modified DESC") + LiveData<List<Note>> searchFavoritesByModified(long accountId, String query); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY title COLLATE NOCASE ASC") + LiveData<List<Note>> searchFavoritesLexicographically(long accountId, String query); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, modified DESC") + LiveData<List<Note>> searchUncategorizedByModified(long accountId, String query); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, title COLLATE NOCASE ASC") + LiveData<List<Note>> searchUncategorizedLexicographically(long accountId, String query); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, modified DESC") + LiveData<List<Note>> searchCategoryByModified(long accountId, String query, String category); + + @Query("SELECT * FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, title COLLATE NOCASE ASC") + LiveData<List<Note>> searchCategoryLexicographically(long accountId, String query, String category); @Query("DELETE FROM NOTE WHERE id = :id AND status = :forceDBStatus") void deleteByNoteId(long id, DBStatus forceDBStatus); @@ -73,17 +57,14 @@ public interface NoteDao { @Query("UPDATE NOTE SET scrollY = :scrollY WHERE id = :id") void updateScrollY(long id, int scrollY); - @Query("SELECT NOTE.*, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id WHERE NOTE.id = :id") - NoteWithCategory getFullNoteWithCategory(long id); - - @Query("SELECT NOTE.*, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id WHERE NOTE.id = :id AND NOTE.accountId = :accountId AND status != :accountId") - LiveData<NoteWithCategory> getNoteWithCategoryLiveData(long accountId, long id); + @Query("SELECT * FROM NOTE WHERE id = :id") + Note getNoteById(long id); @Query("UPDATE NOTE SET status = :status WHERE id = :id") void updateStatus(long id, DBStatus status); - @Query("UPDATE NOTE SET categoryId = :categoryId WHERE id = :id") - void updateCategory(long id, long categoryId); + @Query("UPDATE NOTE SET category = :category WHERE id = :id") + void updateCategory(long id, String category); /** * Gets all the remoteIds of all not deleted notes of an account @@ -117,8 +98,8 @@ public interface NoteDao { * * @return {@link List<Note>} */ - @Query("SELECT NOTE.*, CATEGORY.title as 'category' FROM NOTE INNER JOIN CATEGORY ON categoryId = CATEGORY.id WHERE status != '' AND NOTE.accountId = :accountId") - List<NoteWithCategory> getLocalModifiedNotes(long accountId); + @Query("SELECT * FROM NOTE WHERE status != '' AND accountId = :accountId") + List<Note> getLocalModifiedNotes(long accountId); @Query("SELECT * FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId ORDER BY modified DESC LIMIT 4") List<Note> getRecentNotes(long accountId); @@ -133,17 +114,31 @@ public interface NoteDao { * used by: {@link NoteServerSyncHelper.SyncTask#pushLocalChanges()} update only, if not modified locally during the synchronization * (i.e. all (!) user changeable columns (content, favorite, category) must still have the same value), uses reference value gathered at start of synchronization */ + @SuppressWarnings("JavadocReference") @Query("UPDATE NOTE SET title = :title, modified = :modified, title = :title, favorite = :favorite, etag = :eTag, content = :content, status = '', excerpt = :excerpt " + - "WHERE id = :id AND content = :oldContent AND favorite = :oldFavorite AND categoryId = :oldCategoryId") - void updateIfNotModifiedLocallyDuringSync(long id, Long modified, String title, boolean favorite, String eTag, String content, String excerpt, String oldContent, boolean oldFavorite, long oldCategoryId); + "WHERE id = :id AND content = :oldContent AND favorite = :oldFavorite AND category = :oldCategory") + int updateIfNotModifiedLocallyDuringSync(long id, Long modified, String title, boolean favorite, String eTag, String content, String excerpt, String oldContent, String oldCategory, boolean oldFavorite); /** * used by: {@link NoteServerSyncHelper.SyncTask#pullRemoteChanges()} update only, if not modified locally (i.e. STATUS="") and if modified remotely (i.e. any (!) column has changed) */ + @SuppressWarnings("JavadocReference") @Query("UPDATE NOTE SET id = :id, title = :title, modified = :modified, title = :title, favorite = :favorite, etag = :eTag, content = :content, status = '', excerpt = :excerpt " + - "WHERE id = :id AND status = '' AND (modified != :modified OR favorite != :favorite OR categoryId != :categoryTitle OR (eTag == NULL OR eTag != :eTag) OR content != :content)") - void updateIfNotModifiedLocallyAndRemoteColumnHasChanged(long id, Long modified, String title, boolean favorite, String categoryTitle, String eTag, String content, String excerpt); + "WHERE id = :id AND status = '' AND (modified != :modified OR favorite != :favorite OR category != :category OR (eTag == NULL OR eTag != :eTag) OR content != :content)") + void updateIfNotModifiedLocallyAndRemoteColumnHasChanged(long id, Long modified, String title, boolean favorite, String category, String eTag, String content, String excerpt); @Query("SELECT content FROM NOTE WHERE id = :id") String getContent(Long id); + + /** + * This method return all of the categories with given accountId + * + * @param accountId The user account Id + * @return All of the categories with given accountId + */ + @Query("SELECT accountId, category, COUNT(*) as 'totalNotes' FROM NOTE WHERE STATUS != 'LOCAL_DELETED' AND accountId = :accountId GROUP BY category") + LiveData<List<CategoryWithNotesCount>> getCategoriesLiveData(Long accountId); + + @Query("SELECT accountId, category, COUNT(*) as 'totalNotes' FROM NOTE WHERE category != '' AND STATUS != 'LOCAL_DELETED' AND accountId = :accountId AND category LIKE :searchTerm GROUP BY category") + LiveData<List<CategoryWithNotesCount>> searchCategories(Long accountId, String searchTerm); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Category.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Category.java deleted file mode 100644 index b87b8ea3..00000000 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Category.java +++ /dev/null @@ -1,97 +0,0 @@ -package it.niedermann.owncloud.notes.persistence.entity; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Index; -import androidx.room.PrimaryKey; - -import java.io.Serializable; - -import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; - -@Entity( - foreignKeys = { - @ForeignKey( - entity = Account.class, - parentColumns = "id", - childColumns = "accountId", - onDelete = ForeignKey.CASCADE - ) - }, - indices = { - @Index(name = "IDX_CATEGORIES_ACCOUNTID", value = "accountId"), - @Index(name = "IDX_CATEGORIES_ID", value = "id"), - @Index(name = "IDX_CATEGORIES_SORTING_METHOD", value = "sortingMethod"), - @Index(name = "IDX_CATEGORIES_TITLE", value = "title"), - @Index(name = "IDX_UNIQUE_ACCOUNT_TITLE", value = {"accountId", "title"}, unique = true) - } -) -public class Category implements Serializable { - @PrimaryKey(autoGenerate = true) - private long id; - private long accountId; - @NonNull - @ColumnInfo(defaultValue = "") - private String title = ""; - @Nullable - private CategorySortingMethod sortingMethod; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public long getAccountId() { - return accountId; - } - - public void setAccountId(long accountId) { - this.accountId = accountId; - } - - @NonNull - public String getTitle() { - return title; - } - - public void setTitle(@NonNull String title) { - this.title = title; - } - - @Nullable - public CategorySortingMethod getSortingMethod() { - return sortingMethod; - } - - public void setSortingMethod(@Nullable CategorySortingMethod sortingMethod) { - this.sortingMethod = sortingMethod; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Category)) return false; - - Category category = (Category) o; - - if (id != category.id) return false; - if (accountId != category.accountId) return false; - if (!title.equals(category.title)) return false; - return sortingMethod == category.sortingMethod; - } - - @Override - public int hashCode() { - int result = (int) (id ^ (id >>> 32)); - result = 31 * result + (int) (accountId ^ (accountId >>> 32)); - result = 31 * result + title.hashCode(); - result = 31 * result + (sortingMethod != null ? sortingMethod.hashCode() : 0); - return result; - } -}
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryOptions.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryOptions.java new file mode 100644 index 00000000..eb1e8c73 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryOptions.java @@ -0,0 +1,103 @@ +package it.niedermann.owncloud.notes.persistence.entity; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Ignore; +import androidx.room.Index; + +import java.io.Serializable; + +import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; + +@Entity( + primaryKeys = { + "accountId", + "category" + }, + foreignKeys = { + @ForeignKey( + entity = Account.class, + parentColumns = "id", + childColumns = "accountId", + onDelete = ForeignKey.CASCADE + ), +// Not possible with SQLite because parent column is not unique +// @ForeignKey( +// entity = Note.class, +// parentColumns = {"accountId", "category"}, +// childColumns = {"accountId", "category"}, +// onDelete = ForeignKey.CASCADE +// ) + }, + indices = { + @Index(name = "IDX_CATEGORIYOPTIONS_ACCOUNTID", value = "accountId"), + @Index(name = "IDX_CATEGORIYOPTIONS_CATEGORY", value = "category"), + @Index(name = "IDX_CATEGORIYOPTIONS_SORTING_METHOD", value = "sortingMethod"), + @Index(name = "IDX_UNIQUE_CATEGORYOPTIONS_ACCOUNT_CATEGORY", value = {"accountId", "category"}, unique = true) + } +) +public class CategoryOptions implements Serializable { + private long accountId; + @NonNull + private String category = ""; + @Nullable + private CategorySortingMethod sortingMethod; + + public CategoryOptions() { + // Default constructor + } + + @Ignore + public CategoryOptions(long accountId, String category) { + setAccountId(accountId); + setCategory(category); + } + + public long getAccountId() { + return accountId; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + @NonNull + public String getCategory() { + return category; + } + + public void setCategory(@NonNull String category) { + this.category = category; + } + + @Nullable + public CategorySortingMethod getSortingMethod() { + return sortingMethod; + } + + public void setSortingMethod(@Nullable CategorySortingMethod sortingMethod) { + this.sortingMethod = sortingMethod; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CategoryOptions)) return false; + + CategoryOptions that = (CategoryOptions) o; + + if (accountId != that.accountId) return false; + if (!category.equals(that.category)) return false; + return sortingMethod == that.sortingMethod; + } + + @Override + public int hashCode() { + int result = (int) (accountId ^ (accountId >>> 32)); + result = 31 * result + category.hashCode(); + result = 31 * result + (sortingMethod != null ? sortingMethod.hashCode() : 0); + return result; + } +}
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryWithNotesCount.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryWithNotesCount.java index 7c1cbcec..ecdeae58 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryWithNotesCount.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/CategoryWithNotesCount.java @@ -2,8 +2,8 @@ package it.niedermann.owncloud.notes.persistence.entity; public class CategoryWithNotesCount { - private Long id; - private String title; + private long accountId; + private String category; private Integer totalNotes; public Integer getTotalNotes() { @@ -14,20 +14,20 @@ public class CategoryWithNotesCount { this.totalNotes = totalNotes; } - public String getTitle() { - return title; + public long getAccountId() { + return accountId; } - public void setTitle(String title) { - this.title = title; + public void setAccountId(long accountId) { + this.accountId = accountId; } - public Long getId() { - return id; + public String getCategory() { + return category; } - public void setId(Long id) { - this.id = id; + public void setCategory(String category) { + this.category = category; } @Override @@ -37,15 +37,16 @@ public class CategoryWithNotesCount { CategoryWithNotesCount that = (CategoryWithNotesCount) o; - if (id != null ? !id.equals(that.id) : that.id != null) return false; - if (title != null ? !title.equals(that.title) : that.title != null) return false; + if (accountId != that.accountId) return false; + if (category != null ? !category.equals(that.category) : that.category != null) + return false; return totalNotes != null ? totalNotes.equals(that.totalNotes) : that.totalNotes == null; } @Override public int hashCode() { - int result = id != null ? id.hashCode() : 0; - result = 31 * result + (title != null ? title.hashCode() : 0); + int result = (int) (accountId ^ (accountId >>> 32)); + result = 31 * result + (category != null ? category.hashCode() : 0); result = 31 * result + (totalNotes != null ? totalNotes.hashCode() : 0); return result; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java index 0dada540..7224d4eb 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java @@ -13,6 +13,7 @@ import java.io.Serializable; import java.util.Calendar; import it.niedermann.owncloud.notes.shared.model.DBStatus; +import it.niedermann.owncloud.notes.shared.model.Item; @Entity( foreignKeys = { @@ -21,23 +22,18 @@ import it.niedermann.owncloud.notes.shared.model.DBStatus; parentColumns = "id", childColumns = "accountId", onDelete = ForeignKey.CASCADE - ), - @ForeignKey( - entity = Category.class, - parentColumns = "id", - childColumns = "categoryId" ) }, indices = { @Index(name = "IDX_NOTE_ACCOUNTID", value = "accountId"), - @Index(name = "IDX_NOTE_CATEGORY", value = "categoryId"), + @Index(name = "IDX_NOTE_CATEGORY", value = "category"), @Index(name = "IDX_NOTE_FAVORITE", value = "favorite"), @Index(name = "IDX_NOTE_MODIFIED", value = "modified"), @Index(name = "IDX_NOTE_REMOTEID", value = "remoteId"), @Index(name = "IDX_NOTE_STATUS", value = "status") } ) -public class Note implements Serializable { +public class Note implements Serializable, Item { @PrimaryKey(autoGenerate = true) private long id; @Nullable @@ -48,6 +44,9 @@ public class Note implements Serializable { @NonNull @ColumnInfo(defaultValue = "") private String title = ""; + @NonNull + @ColumnInfo(defaultValue = "") + private String category = ""; @Nullable private Calendar modified; @NonNull @@ -56,8 +55,6 @@ public class Note implements Serializable { @ColumnInfo(defaultValue = "0") private boolean favorite = false; @Nullable - private Long categoryId; - @Nullable private String eTag; @NonNull @ColumnInfo(defaultValue = "") @@ -70,18 +67,19 @@ public class Note implements Serializable { } @Ignore - public Note(@Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, boolean favorite, @Nullable String eTag) { + public Note(@Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, @NonNull String category, boolean favorite, @Nullable String eTag) { this.remoteId = remoteId; this.title = title; this.modified = modified; this.content = content; this.favorite = favorite; + this.category = category; this.eTag = eTag; } @Ignore - public Note(long id, @Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, boolean favorite, @Nullable String etag, @NonNull DBStatus status, long accountId, @NonNull String excerpt, int scrollY) { - this(remoteId, modified, title, content, favorite, etag); + public Note(long id, @Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, @NonNull String category, boolean favorite, @Nullable String etag, @NonNull DBStatus status, long accountId, @NonNull String excerpt, int scrollY) { + this(remoteId, modified, title, content, category, favorite, etag); this.id = id; this.status = status; this.accountId = accountId; @@ -97,6 +95,15 @@ public class Note implements Serializable { this.id = id; } + @NonNull + public String getCategory() { + return category; + } + + public void setCategory(@NonNull String category) { + this.category = category; + } + @Nullable public Long getRemoteId() { return remoteId; @@ -159,15 +166,6 @@ public class Note implements Serializable { } @Nullable - public Long getCategoryId() { - return categoryId; - } - - public void setCategoryId(@Nullable Long categoryId) { - this.categoryId = categoryId; - } - - @Nullable public String getETag() { return eTag; } @@ -208,11 +206,10 @@ public class Note implements Serializable { return false; if (status != note.status) return false; if (!title.equals(note.title)) return false; + if (!category.equals(note.category)) return false; if (modified != null ? !modified.equals(note.modified) : note.modified != null) return false; if (!content.equals(note.content)) return false; - if (categoryId != null ? !categoryId.equals(note.categoryId) : note.categoryId != null) - return false; if (eTag != null ? !eTag.equals(note.eTag) : note.eTag != null) return false; return excerpt.equals(note.excerpt); } @@ -224,29 +221,30 @@ public class Note implements Serializable { result = 31 * result + (int) (accountId ^ (accountId >>> 32)); result = 31 * result + status.hashCode(); result = 31 * result + title.hashCode(); + result = 31 * result + category.hashCode(); result = 31 * result + (modified != null ? modified.hashCode() : 0); result = 31 * result + content.hashCode(); result = 31 * result + (favorite ? 1 : 0); - result = 31 * result + (categoryId != null ? categoryId.hashCode() : 0); result = 31 * result + (eTag != null ? eTag.hashCode() : 0); result = 31 * result + excerpt.hashCode(); result = 31 * result + scrollY; return result; } - @NonNull @Override public String toString() { - return "NoteEntity{" + + return "Note{" + "id=" + id + ", remoteId=" + remoteId + ", accountId=" + accountId + - ", categoryId=" + categoryId + ", status=" + status + ", title='" + title + '\'' + + ", category='" + category + '\'' + ", modified=" + modified + + ", content='" + content + '\'' + ", favorite=" + favorite + ", eTag='" + eTag + '\'' + + ", excerpt='" + excerpt + '\'' + ", scrollY=" + scrollY + '}'; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NoteWithCategory.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NoteWithCategory.java deleted file mode 100644 index 187839bc..00000000 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NoteWithCategory.java +++ /dev/null @@ -1,130 +0,0 @@ -package it.niedermann.owncloud.notes.persistence.entity; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.room.Embedded; -import androidx.room.Ignore; - -import java.io.Serializable; -import java.util.Calendar; - -import it.niedermann.owncloud.notes.shared.model.DBStatus; -import it.niedermann.owncloud.notes.shared.model.Item; - -public class NoteWithCategory implements Serializable, Item { - @Embedded - private Note note; - @NonNull - private String category = ""; - - public NoteWithCategory() { - // Default constructor - } - - @Ignore - public NoteWithCategory(@NonNull Note note) { - this.note = note; - } - - @Ignore - public NoteWithCategory(@NonNull Note note, @NonNull String category) { - this.note = note; - this.category = category; - } - - @NonNull - public Note getNote() { - return note; - } - - public void setNote(@NonNull Note note) { - this.note = note; - } - - public long getId() { - return note.getId(); - } - - @Nullable - public Long getRemoteId() { - return note.getRemoteId(); - } - - public long getAccountId() { - return note.getAccountId(); - } - - @NonNull - public DBStatus getStatus() { - return note.getStatus(); - } - - @NonNull - public String getTitle() { - return note.getTitle(); - } - - @Nullable - public Calendar getModified() { - return note.getModified(); - } - - @NonNull - public String getContent() { - return note.getContent(); - } - - public boolean getFavorite() { - return note.getFavorite(); - } - - @Nullable - public String getETag() { - return note.getETag(); - } - - @NonNull - public String getExcerpt() { - return note.getExcerpt(); - } - - public int getScrollY() { - return note.getScrollY(); - } - - @NonNull - public String getCategory() { - return category; - } - - public void setCategory(@NonNull String category) { - this.category = category; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof NoteWithCategory)) return false; - - NoteWithCategory that = (NoteWithCategory) o; - - if (note != null ? !note.equals(that.note) : that.note != null) return false; - return category.equals(that.category); - } - - @Override - public int hashCode() { - int result = note != null ? note.hashCode() : 0; - result = 31 * result + category.hashCode(); - return result; - } - - @NonNull - @Override - public String toString() { - return "NoteWithCategory{" + - "note=" + note + - ", category='" + category + '\'' + - '}'; - } -} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NotesListWidgetData.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NotesListWidgetData.java index a7d95172..06f3fe5a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NotesListWidgetData.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/NotesListWidgetData.java @@ -19,15 +19,16 @@ import it.niedermann.owncloud.notes.widget.AbstractWidgetData; onDelete = ForeignKey.CASCADE ), @ForeignKey( - entity = Category.class, - parentColumns = "id", - childColumns = "categoryId", + entity = CategoryOptions.class, + parentColumns = {"accountId", "category"}, + childColumns = {"accountId", "category"}, onDelete = ForeignKey.CASCADE ) }, indices = { @Index(name = "IDX_NOTESLISTWIDGETDATA_ACCOUNTID", value = "accountId"), - @Index(name = "IDX_NOTESLISTWIDGETDATA_CATEGORYID", value = "categoryId"), + @Index(name = "IDX_NOTESLISTWIDGETDATA_CATEGORY", value = "category"), + @Index(name = "IDX_NOTESLISTWIDGETDATA_ACCOUNT_CATEGORY", value = {"accountId", "category"}) } ) public class NotesListWidgetData extends AbstractWidgetData { @@ -41,16 +42,17 @@ public class NotesListWidgetData extends AbstractWidgetData { @IntRange(from = 0, to = 2) private int mode; + @Nullable - private Long categoryId; + private String category; @Nullable - public Long getCategoryId() { - return categoryId; + public String getCategory() { + return category; } - public void setCategoryId(@Nullable Long categoryId) { - this.categoryId = categoryId; + public void setCategory(@Nullable String category) { + this.category = category; } public void setMode(@IntRange(from = 0, to = 2) int mode) { @@ -66,17 +68,19 @@ public class NotesListWidgetData extends AbstractWidgetData { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof NotesListWidgetData)) return false; + if (!super.equals(o)) return false; NotesListWidgetData that = (NotesListWidgetData) o; if (mode != that.mode) return false; - return categoryId != null ? categoryId.equals(that.categoryId) : that.categoryId == null; + return category != null ? category.equals(that.category) : that.category == null; } @Override public int hashCode() { - int result = mode; - result = 31 * result + (categoryId != null ? categoryId.hashCode() : 0); + int result = super.hashCode(); + result = 31 * result + mode; + result = 31 * result + (category != null ? category.hashCode() : 0); return result; } @@ -85,7 +89,7 @@ public class NotesListWidgetData extends AbstractWidgetData { public String toString() { return "NotesListWidgetData{" + "mode=" + mode + - ", categoryId=" + categoryId + + ", category='" + category + '\'' + '}'; } }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/migration/Migration_19_20.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/migration/Migration_19_20.java index b213d8a1..056880cf 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/migration/Migration_19_20.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/migration/Migration_19_20.java @@ -38,24 +38,24 @@ public class Migration_19_20 extends Migration { db.execSQL("DROP INDEX NOTES_MODIFIED_idx"); db.execSQL("CREATE TABLE `Account` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL DEFAULT '', `userName` TEXT NOT NULL DEFAULT '', `accountName` TEXT NOT NULL DEFAULT '', `eTag` TEXT, `modified` INTEGER, `apiVersion` TEXT, `color` INTEGER NOT NULL DEFAULT -16743735, `textColor` INTEGER NOT NULL DEFAULT -16777216, `capabilitiesETag` TEXT)"); - db.execSQL("CREATE TABLE `Category` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountId` INTEGER NOT NULL, `title` TEXT NOT NULL DEFAULT '', `sortingMethod` INTEGER, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); - db.execSQL("CREATE TABLE `Note` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remoteId` INTEGER, `accountId` INTEGER NOT NULL, `status` TEXT NOT NULL, `title` TEXT NOT NULL DEFAULT '', `modified` INTEGER, `content` TEXT NOT NULL DEFAULT '', `favorite` INTEGER NOT NULL DEFAULT 0, `categoryId` INTEGER, `eTag` TEXT, `excerpt` TEXT NOT NULL DEFAULT '', `scrollY` INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`categoryId`) REFERENCES `Category`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )"); - db.execSQL("CREATE TABLE `NotesListWidgetData` (`mode` INTEGER NOT NULL, `categoryId` INTEGER, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`categoryId`) REFERENCES `Category`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); + db.execSQL("CREATE TABLE `CategoryOptions` (`accountId` INTEGER NOT NULL, `category` TEXT NOT NULL, `sortingMethod` INTEGER, PRIMARY KEY(`accountId`, `category`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); + db.execSQL("CREATE TABLE `Note` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remoteId` INTEGER, `accountId` INTEGER NOT NULL, `status` TEXT NOT NULL, `title` TEXT NOT NULL DEFAULT '', `category` TEXT NOT NULL DEFAULT '', `modified` INTEGER, `content` TEXT NOT NULL DEFAULT '', `favorite` INTEGER NOT NULL DEFAULT 0, `eTag` TEXT, `excerpt` TEXT NOT NULL DEFAULT '', `scrollY` INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); + db.execSQL("CREATE TABLE `NotesListWidgetData` (`mode` INTEGER NOT NULL, `category` TEXT, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`, `category`) REFERENCES `CategoryOptions`(`accountId`, `category`) ON UPDATE NO ACTION ON DELETE CASCADE )"); db.execSQL("CREATE TABLE `SingleNoteWidgetData` (`noteId` INTEGER NOT NULL, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`noteId`) REFERENCES `Note`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); db.execSQL("CREATE INDEX `IDX_ACCOUNT_ACCOUNTNAME` ON `Account` (`accountName`)"); + db.execSQL("CREATE INDEX `IDX_ACCOUNT_ETAG` ON `Account` (`eTag`)"); + db.execSQL("CREATE INDEX `IDX_ACCOUNT_MODIFIED` ON `Account` (`modified`)"); db.execSQL("CREATE INDEX `IDX_ACCOUNT_URL` ON `Account` (`url`)"); db.execSQL("CREATE INDEX `IDX_ACCOUNT_USERNAME` ON `Account` (`userName`)"); - db.execSQL("CREATE INDEX `IDX_ACCOUNT_MODIFIED` ON `Account` (`modified`)"); - db.execSQL("CREATE INDEX `IDX_ACCOUNT_ETAG` ON `Account` (`eTag`)"); - db.execSQL("CREATE INDEX `IDX_CATEGORIES_ACCOUNTID` ON `Category` (`accountId`)"); - db.execSQL("CREATE INDEX `IDX_CATEGORIES_ID` ON `Category` (`id`)"); - db.execSQL("CREATE INDEX `IDX_CATEGORIES_SORTING_METHOD` ON `Category` (`sortingMethod`)"); - db.execSQL("CREATE INDEX `IDX_CATEGORIES_TITLE` ON `Category` (`title`)"); + db.execSQL("CREATE INDEX `IDX_CATEGORIYOPTIONS_ACCOUNTID` ON `Category` (`accountId`)"); + db.execSQL("CREATE INDEX `IDX_CATEGORIYOPTIONS_CATEGORY` ON `Category` (`category`)"); + db.execSQL("CREATE INDEX `IDX_CATEGORIYOPTIONS_SORTING_METHOD` ON `Category` (`sortingMethod`)"); db.execSQL("CREATE INDEX `IDX_NOTESLISTWIDGETDATA_ACCOUNTID` ON `NotesListWidgetData` (`accountId`)"); - db.execSQL("CREATE INDEX `IDX_NOTESLISTWIDGETDATA_CATEGORYID` ON `NotesListWidgetData` (`categoryId`)"); + db.execSQL("CREATE INDEX `IDX_NOTESLISTWIDGETDATA_CATEGORY` ON `NotesListWidgetData` (`category`)"); + db.execSQL("CREATE INDEX `IDX_NOTESLISTWIDGETDATA_ACCOUNT_CATEGORY` ON `NotesListWidgetData` (`accountId`, `category`)"); db.execSQL("CREATE INDEX `IDX_NOTE_ACCOUNTID` ON `Note` (`accountId`)"); - db.execSQL("CREATE INDEX `IDX_NOTE_CATEGORY` ON `Note` (`categoryId`)"); + db.execSQL("CREATE INDEX `IDX_NOTE_CATEGORY` ON `Note` (`category`)"); db.execSQL("CREATE INDEX `IDX_NOTE_FAVORITE` ON `Note` (`favorite`)"); db.execSQL("CREATE INDEX `IDX_NOTE_MODIFIED` ON `Note` (`modified`)"); db.execSQL("CREATE INDEX `IDX_NOTE_REMOTEID` ON `Note` (`remoteId`)"); @@ -63,10 +63,10 @@ public class Migration_19_20 extends Migration { db.execSQL("CREATE INDEX `IDX_SINGLENOTEWIDGETDATA_ACCOUNTID` ON `SingleNoteWidgetData` (`accountId`)"); db.execSQL("CREATE INDEX `IDX_SINGLENOTEWIDGETDATA_NOTEID` ON `SingleNoteWidgetData` (`noteId`)"); - db.execSQL("CREATE UNIQUE INDEX `IDX_UNIQUE_ACCOUNT_TITLE` ON `Category` (`accountId`, `title`)"); + db.execSQL("CREATE UNIQUE INDEX `IDX_UNIQUE_CATEGORYOPTIONS_ACCOUNT_CATEGORY` ON `Category` (`accountId`, `sortingMethod`)"); - db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_DEL AFTER DELETE ON Note BEGIN DELETE FROM Category WHERE Category.id NOT IN (SELECT Note.categoryId FROM Note); END;"); - db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_UPD AFTER UPDATE ON Note BEGIN DELETE FROM Category WHERE Category.id NOT IN (SELECT Note.categoryId FROM Note); END;"); + db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_DEL AFTER DELETE ON Note BEGIN DELETE FROM CategoryOptions WHERE CategoryOptions.category NOT IN (SELECT Note.category FROM Note WHERE Note.accountId = CategoryOptions.accountId); END;"); + db.execSQL("CREATE TRIGGER TRG_CLEANUP_CATEGORIES_UPD AFTER UPDATE ON Note BEGIN DELETE FROM CategoryOptions WHERE CategoryOptions.category NOT IN (SELECT Note.category FROM Note WHERE Note.accountId = CategoryOptions.accountId); END;"); Cursor tmpAccountCursor = db.query("SELECT * FROM ACCOUNTS", null); while (tmpAccountCursor.moveToNext()) { @@ -99,16 +99,15 @@ public class Migration_19_20 extends Migration { Cursor tmpCategoriesCursor = db.query("SELECT * FROM CATEGORIES", null); while (tmpCategoriesCursor.moveToNext()) { ContentValues values = new ContentValues(); - values.put("ID", tmpCategoriesCursor.getInt(0)); values.put("ACCOUNTID", tmpCategoriesCursor.getInt(1)); - values.put("TITLE", tmpCategoriesCursor.getString(2)); + values.put("CATEGORY", tmpCategoriesCursor.getString(2)); values.put("SORTINGMETHOD", tmpCategoriesCursor.getInt(3)); db.insert("CATEGORY", OnConflictStrategy.REPLACE, values); } tmpCategoriesCursor.close(); db.execSQL("DROP TABLE IF EXISTS CATEGORIES"); - Cursor tmpNotesCursor = db.query("SELECT * FROM NOTES", null); + Cursor tmpNotesCursor = db.query("SELECT NOTES.*, CATEGORIES.title as `CAT_TITLE` FROM NOTES INNER JOIN CATEGORIES ON NOTES.categoryId = CATEGORIES.id", null); while (tmpNotesCursor.moveToNext()) { ContentValues values = new ContentValues(); values.put("ID", tmpNotesCursor.getInt(0)); @@ -119,7 +118,7 @@ public class Migration_19_20 extends Migration { values.put("MODIFIED", tmpNotesCursor.getLong(5)); values.put("CONTENT", tmpNotesCursor.getString(6)); values.put("FAVORITE", tmpNotesCursor.getInt(7)); - values.put("CATEGORYID", tmpNotesCursor.getInt(8)); + values.put("CATEGORY", tmpNotesCursor.getInt(11)); values.put("ETAG", tmpNotesCursor.getString(9)); values.put("EXCERPT", tmpNotesCursor.getString(10)); db.insert("NOTE", OnConflictStrategy.REPLACE, values); @@ -141,7 +140,7 @@ public class Migration_19_20 extends Migration { db.execSQL("DROP TABLE IF EXISTS WIDGET_NOTE_LISTS"); Cursor tmpWidgetSinlgeNotesCursor = db.query("SELECT * FROM WIDGET_SINGLE_NOTES", null); - while (tmpWidgetNotesListCursor.moveToNext()) { + while (tmpWidgetSinlgeNotesCursor.moveToNext()) { ContentValues values = new ContentValues(); values.put("ID", tmpWidgetNotesListCursor.getInt(0)); values.put("ACCOUNTID", tmpWidgetNotesListCursor.getInt(1)); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NavigationCategory.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NavigationCategory.java index 53b3c2cd..52a3a117 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NavigationCategory.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NavigationCategory.java @@ -5,8 +5,6 @@ import androidx.annotation.Nullable; import java.io.Serializable; -import it.niedermann.owncloud.notes.persistence.entity.Category; - import static it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.DEFAULT_CATEGORY; public class NavigationCategory implements Serializable { @@ -14,19 +12,22 @@ public class NavigationCategory implements Serializable { @NonNull private final ENavigationCategoryType type; @Nullable - private final Category category; + private final String category; + private final long accountId; public NavigationCategory(@NonNull ENavigationCategoryType type) { if (type == DEFAULT_CATEGORY) { - throw new IllegalArgumentException("If you want to provide a " + DEFAULT_CATEGORY + ", call the constructor with a " + Category.class.getSimpleName()); + throw new IllegalArgumentException("If you want to provide a " + DEFAULT_CATEGORY + ", call the constructor with an accountId and category as arguments"); } this.type = type; this.category = null; + this.accountId = Long.MIN_VALUE; } - public NavigationCategory(@NonNull Category category) { + public NavigationCategory(long accountId, @Nullable String category) { this.type = DEFAULT_CATEGORY; this.category = category; + this.accountId = accountId; } @NonNull @@ -34,8 +35,12 @@ public class NavigationCategory implements Serializable { return type; } + public long getAccountId() { + return accountId; + } + @Nullable - public Category getCategory() { + public String getCategory() { return category; } @@ -46,6 +51,7 @@ public class NavigationCategory implements Serializable { NavigationCategory that = (NavigationCategory) o; + if (accountId != that.accountId) return false; if (type != that.type) return false; return category != null ? category.equals(that.category) : that.category == null; } @@ -54,6 +60,7 @@ public class NavigationCategory implements Serializable { public int hashCode() { int result = type.hashCode(); result = 31 * result + (category != null ? category.hashCode() : 0); + result = 31 * result + (int) (accountId ^ (accountId >>> 32)); return result; } @@ -62,7 +69,8 @@ public class NavigationCategory implements Serializable { public String toString() { return "NavigationCategory{" + "type=" + type + - ", category=" + category + + ", category='" + category + '\'' + + ", accountId=" + accountId + '}'; } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerResponse.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerResponse.java index fbf94237..6ac4e12d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerResponse.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerResponse.java @@ -8,12 +8,10 @@ import org.json.JSONObject; import java.util.ArrayList; import java.util.Calendar; -import java.util.GregorianCalendar; import java.util.List; import it.niedermann.owncloud.notes.persistence.NotesClient; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; /** * Provides entity classes for handling server responses with a single note ({@link NoteResponse}) or a list of notes ({@link NotesResponse}). @@ -25,7 +23,7 @@ public class ServerResponse { super(response); } - public NoteWithCategory getNote() throws JSONException { + public Note getNote() throws JSONException { return getNoteFromJSON(new JSONObject(getContent())); } } @@ -35,8 +33,8 @@ public class ServerResponse { super(response); } - public List<NoteWithCategory> getNotes() throws JSONException { - List<NoteWithCategory> notesList = new ArrayList<>(); + public List<Note> getNotes() throws JSONException { + List<Note> notesList = new ArrayList<>(); JSONArray notes = new JSONArray(getContent()); for (int i = 0; i < notes.length(); i++) { JSONObject json = notes.getJSONObject(i); @@ -70,7 +68,7 @@ public class ServerResponse { return response.getSupportedApiVersions(); } - NoteWithCategory getNoteFromJSON(JSONObject json) throws JSONException { + Note getNoteFromJSON(JSONObject json) throws JSONException { long id = 0; String title = ""; String content = ""; @@ -100,6 +98,6 @@ public class ServerResponse { if (!json.isNull(NotesClient.JSON_ETAG)) { etag = json.getString(NotesClient.JSON_ETAG); } - return new NoteWithCategory(new Note(id, modified, title, content, favorite, etag), category); + return new Note(id, modified, title, content, category, favorite, etag); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/DisplayUtils.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/DisplayUtils.java index 68e6ee7c..fcd418e8 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/DisplayUtils.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/DisplayUtils.java @@ -144,7 +144,7 @@ public class DisplayUtils { public static NavigationItem.CategoryNavigationItem convertToCategoryNavigationItem(@NonNull Context context, @NonNull CategoryWithNotesCount counter) { Resources res = context.getResources(); - String category = counter.getTitle().toLowerCase(); + String category = counter.getCategory().toLowerCase(); int icon = NavigationAdapter.ICON_FOLDER; if (category.equals(res.getString(R.string.category_music).toLowerCase())) { icon = R.drawable.ic_library_music_grey600_24dp; @@ -153,6 +153,6 @@ public class DisplayUtils { } else if (category.equals(res.getString(R.string.category_work).toLowerCase())) { icon = R.drawable.ic_work_grey600_24dp; } - return new NavigationItem.CategoryNavigationItem("category:" + counter.getTitle(), counter.getTitle(), counter.getTotalNotes(), icon, counter.getId()); + return new NavigationItem.CategoryNavigationItem("category:" + counter.getCategory(), counter.getCategory(), counter.getTotalNotes(), icon, counter.getAccountId(), counter.getCategory()); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.java index 84a15231..6b6d5050 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.java @@ -46,10 +46,7 @@ public class NoteListWidget extends AppWidgetProvider { if (data != null) { final Account localAccount = db.getAccountDao().getAccount(data.getAccountId()); - String category = null; - if (data.getCategoryId() != null) { - category = db.getCategoryDao().getCategoryTitleById(data.getCategoryId()); - } + String category = data.getCategory(); darkTheme = DarkModeSetting.fromModeID(data.getThemeMode()); @@ -72,7 +69,7 @@ public class NoteListWidget extends AppWidgetProvider { 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))), + : new NavigationCategory(localAccount.getId(), category)), PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent templatePI = PendingIntent.getActivity(context, PENDING_INTENT_EDIT_NOTE_RQ, diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetConfigurationActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetConfigurationActivity.java index c2ef6122..eb251a9c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetConfigurationActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetConfigurationActivity.java @@ -99,13 +99,13 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { } case UNCATEGORIZED: { data.setMode(MODE_DISPLAY_CATEGORY); - data.setCategoryId(null); + data.setCategory(null); } case DEFAULT_CATEGORY: default: { if (item.getClass() == NavigationItem.CategoryNavigationItem.class) { data.setMode(MODE_DISPLAY_CATEGORY); - data.setCategoryId(((NavigationItem.CategoryNavigationItem) item).categoryId); + data.setCategory(((NavigationItem.CategoryNavigationItem) item).category); } else { data.setMode(MODE_DISPLAY_ALL); Log.e(TAG, "Unknown item navigation type. Fallback to show " + RECENT); @@ -141,7 +141,7 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(adapterCategories); distinctUntilChanged( - map(db.getCategoryDao().getCategoriesLiveData(localAccount.getId()), fromDatabase -> { + map(db.getNoteDao().getCategoriesLiveData(localAccount.getId()), fromDatabase -> { List<NavigationItem.CategoryNavigationItem> categories = convertToCategoryNavigationItem(NoteListWidgetConfigurationActivity.this, fromDatabase); ArrayList<NavigationItem> items = new ArrayList<>(fromDatabase.size() + 3); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java index beb6f87d..5b200f8f 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java @@ -18,10 +18,8 @@ import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.edit.EditNoteActivity; import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.persistence.entity.Note; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData; import it.niedermann.owncloud.notes.preferences.DarkModeSetting; -import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod; import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_ALL; import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_CATEGORY; @@ -35,7 +33,7 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact private final NotesListWidgetData data; private final boolean darkTheme; private NotesDatabase db; - private List<NoteWithCategory> noteEntities; + private List<Note> noteEntities; NoteListWidgetFactory(Context context, Intent intent) { this.context = context; @@ -49,7 +47,7 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact @Override public void onCreate() { - final LiveData<List<NoteWithCategory>> noteEntitiesLiveData; + final LiveData<List<Note>> noteEntitiesLiveData; try { Log.v(TAG, "--- data - " + data); switch (data.getMode()) { @@ -61,8 +59,8 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact break; case MODE_DISPLAY_CATEGORY: default: - if (data.getCategoryId() != null) { - noteEntitiesLiveData = db.getNoteDao().searchCategoryByModified(data.getAccountId(), "%", db.getCategoryDao().getCategoryTitleById(data.getCategoryId())); + if (data.getCategory() != null) { + noteEntitiesLiveData = db.getNoteDao().searchCategoryByModified(data.getAccountId(), "%", data.getCategory()); } else { noteEntitiesLiveData = db.getNoteDao().searchUncategorizedByModified(data.getAccountId(), "%"); } @@ -102,7 +100,7 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact return null; } - Note note = noteEntities.get(position).getNote(); + Note note = noteEntities.get(position); final Intent fillInIntent = new Intent(); final Bundle extras = new Bundle(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetConfigurationActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetConfigurationActivity.java index 7651d5e7..797cc908 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetConfigurationActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetConfigurationActivity.java @@ -16,7 +16,7 @@ import it.niedermann.owncloud.notes.NotesApplication; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.exception.ExceptionHandler; import it.niedermann.owncloud.notes.main.MainActivity; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.SingleNoteWidgetData; public class SingleNoteWidgetConfigurationActivity extends MainActivity { @@ -42,7 +42,7 @@ public class SingleNoteWidgetConfigurationActivity extends MainActivity { @Override public void onNoteClick(int position, View v) { - final NoteWithCategory note = (NoteWithCategory) adapter.getItem(position); + final Note note = (Note) adapter.getItem(position); final Bundle extras = getIntent().getExtras(); if (extras == null) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetFactory.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetFactory.java index 5c09e154..49783eae 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetFactory.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidgetFactory.java @@ -8,17 +8,14 @@ import android.util.Log; import android.widget.RemoteViews; import android.widget.RemoteViewsService; -import java.util.NoSuchElementException; - import it.niedermann.android.markdown.MarkdownUtil; import it.niedermann.owncloud.notes.NotesApplication; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.edit.EditNoteActivity; import it.niedermann.owncloud.notes.persistence.NotesDatabase; -import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory; +import it.niedermann.owncloud.notes.persistence.entity.Note; import it.niedermann.owncloud.notes.persistence.entity.SingleNoteWidgetData; import it.niedermann.owncloud.notes.preferences.DarkModeSetting; -import it.niedermann.owncloud.notes.shared.util.MarkDownUtil; public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFactory { @@ -27,7 +24,7 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa private final int appWidgetId; private NotesDatabase db; - private NoteWithCategory note; + private Note note; private boolean darkModeActive = false; private static final String TAG = SingleNoteWidget.class.getSimpleName(); @@ -56,7 +53,7 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa if (data != null) { final long noteId = data.getNoteId(); Log.v(TAG, "Fetch note with id " + noteId); - note = db.getNoteDao().getFullNoteWithCategory(noteId); + note = db.getNoteDao().getNoteById(noteId); if (note == null) { Log.e(TAG, "Error: note not found"); |