mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-11-23 05:16:15 +03:00
#831 Migrate from SQLiteOpenHelper to Room
This commit is contained in:
parent
0b263beea5
commit
92d0438751
8 changed files with 357 additions and 250 deletions
|
@ -49,7 +49,6 @@ import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
|||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.owncloud.notes.FormattingHelpActivity;
|
||||
|
@ -74,12 +73,9 @@ import it.niedermann.owncloud.notes.main.items.list.NotesListViewItemTouchHelper
|
|||
import it.niedermann.owncloud.notes.main.items.section.SectionItemDecoration;
|
||||
import it.niedermann.owncloud.notes.persistence.CapabilitiesClient;
|
||||
import it.niedermann.owncloud.notes.persistence.CapabilitiesWorker;
|
||||
import it.niedermann.owncloud.notes.persistence.LoadNotesListTask;
|
||||
import it.niedermann.owncloud.notes.persistence.LoadNotesListTask.NotesLoadedListener;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
|
||||
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
|
||||
import it.niedermann.owncloud.notes.persistence.dao.AccountDao;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.Account;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.Note;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory;
|
||||
|
@ -164,14 +160,11 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
swipeRefreshLayout.setRefreshing(false);
|
||||
};
|
||||
|
||||
private LiveData<List<NoteWithCategory>> noteWithCategoryLiveData;
|
||||
private Observer<List<NoteWithCategory>> noteWithCategoryObserver = notes -> {
|
||||
private LiveData<List<Item>> noteWithCategoryLiveData;
|
||||
private Observer<List<Item>> noteWithCategoryObserver = notes -> {
|
||||
adapter.setShowCategory(mainViewModel.getSelectedCategory().getValue() == null);
|
||||
adapter.setHighlightSearchQuery(mainViewModel.getSearchTerm().getValue());
|
||||
List<Item> items = new ArrayList<>();
|
||||
items.addAll(notes);
|
||||
// yes, NoteWithCatecory are Items, check. BUT: setItemList expects an List<Item(!)>, the Elements in notes ARE Items, but the List-type isn't correct, since you pass the List, not the items!
|
||||
adapter.setItemList(items);
|
||||
adapter.setItemList(notes);
|
||||
binding.activityNotesListView.progressCircular.setVisibility(GONE);
|
||||
binding.activityNotesListView.emptyContentView.getRoot().setVisibility(notes.size() > 0 ? GONE : VISIBLE);
|
||||
// if (scrollToTop) {
|
||||
|
@ -196,18 +189,46 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
this.fabCreate = binding.activityNotesListView.fabCreate;
|
||||
this.listView = binding.activityNotesListView.recyclerView;
|
||||
|
||||
mainViewModel.getSelectedCategory().observe(this, (category) -> {
|
||||
View emptyContentView = binding.activityNotesListView.emptyContentView.getRoot();
|
||||
emptyContentView.setVisibility(GONE);
|
||||
binding.activityNotesListView.progressCircular.setVisibility(VISIBLE);
|
||||
this.navigationSelection = category;
|
||||
fabCreate.show();
|
||||
String subtitle;
|
||||
if (navigationSelection.category != null) {
|
||||
if (navigationSelection.category.isEmpty()) {
|
||||
subtitle = getString(R.string.search_in_category, getString(R.string.action_uncategorized));
|
||||
} else {
|
||||
subtitle = getString(R.string.search_in_category, NoteUtil.extendCategory(navigationSelection.category));
|
||||
}
|
||||
} else if (navigationSelection.favorite != null && navigationSelection.favorite) {
|
||||
subtitle = getString(R.string.search_in_category, getString(R.string.label_favorites));
|
||||
} else {
|
||||
subtitle = getString(R.string.search_in_all);
|
||||
}
|
||||
activityBinding.searchText.setText(subtitle);
|
||||
});
|
||||
mainViewModel.filterChanged().observe(this, (v) -> {
|
||||
if (noteWithCategoryLiveData != null) {
|
||||
noteWithCategoryLiveData.removeObserver(noteWithCategoryObserver);
|
||||
}
|
||||
noteWithCategoryLiveData = mainViewModel.getNotesListLiveData();
|
||||
noteWithCategoryLiveData.observe(this, noteWithCategoryObserver);
|
||||
});
|
||||
|
||||
String categoryAdapterSelectedItem = ADAPTER_KEY_RECENT;
|
||||
if (savedInstanceState == null) {
|
||||
if (ACTION_RECENT.equals(getIntent().getAction())) {
|
||||
categoryAdapterSelectedItem = ADAPTER_KEY_RECENT;
|
||||
} else if (ACTION_FAVORITES.equals(getIntent().getAction())) {
|
||||
categoryAdapterSelectedItem = ADAPTER_KEY_STARRED;
|
||||
navigationSelection = new OldCategory(null, true);
|
||||
mainViewModel.postSelectedCategory(new OldCategory(null, true));
|
||||
}
|
||||
} else {
|
||||
Object savedCategory = savedInstanceState.getSerializable(SAVED_STATE_NAVIGATION_SELECTION);
|
||||
if (savedCategory != null) {
|
||||
navigationSelection = (OldCategory) savedCategory;
|
||||
mainViewModel.postSelectedCategory((OldCategory) savedCategory);
|
||||
}
|
||||
navigationOpen = savedInstanceState.getString(SAVED_STATE_NAVIGATION_OPEN);
|
||||
categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION);
|
||||
|
@ -220,11 +241,6 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
activityBinding.activityNotesListView.setBackgroundColor(ContextCompat.getColor(this, R.color.primary));
|
||||
}
|
||||
|
||||
AccountDao dao = db.getAccountDao();
|
||||
new Thread(() -> {
|
||||
List<Account> localAccountEntities = dao.getAccounts();
|
||||
Log.v("TEST", localAccountEntities.size() + " acs");
|
||||
}).start();
|
||||
setupToolbars();
|
||||
setupNavigationList(categoryAdapterSelectedItem);
|
||||
setupNavigationMenu();
|
||||
|
@ -245,6 +261,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
List<Account> localAccounts = db.getAccountDao().getAccounts();
|
||||
if (localAccounts.size() > 0) {
|
||||
localAccount = localAccounts.get(0);
|
||||
mainViewModel.postCurrentAccount(localAccount);
|
||||
}
|
||||
}
|
||||
if (!notAuthorizedAccountHandled) {
|
||||
|
@ -275,6 +292,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
fabCreate.hide();
|
||||
SingleAccountHelper.setCurrentAccount(getApplicationContext(), accountName);
|
||||
localAccount = db.getAccountDao().getLocalAccountByAccountName(accountName);
|
||||
mainViewModel.postCurrentAccount(localAccount);
|
||||
if (localAccount != null) {
|
||||
try {
|
||||
BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor());
|
||||
|
@ -361,7 +379,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
refreshLists();
|
||||
mainViewModel.postSearchTerm(newText);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
@ -457,13 +475,13 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
adapterCategories.setSelectedItem(item.id);
|
||||
// update current selection
|
||||
if (itemRecent.equals(item)) {
|
||||
navigationSelection = new OldCategory(null, null);
|
||||
mainViewModel.postSelectedCategory(new OldCategory(null, null));
|
||||
} else if (itemFavorites.equals(item)) {
|
||||
navigationSelection = new OldCategory(null, true);
|
||||
mainViewModel.postSelectedCategory(new OldCategory(null, true));
|
||||
} else if (itemUncategorized != null && itemUncategorized.equals(item)) {
|
||||
navigationSelection = new OldCategory("", null);
|
||||
mainViewModel.postSelectedCategory(new OldCategory("", null));
|
||||
} else {
|
||||
navigationSelection = new OldCategory(item.label, null);
|
||||
mainViewModel.postSelectedCategory(new OldCategory(item.label, null));
|
||||
}
|
||||
|
||||
// auto-close sub-folder in Navigation if selection is outside of that folder
|
||||
|
@ -686,43 +704,43 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
adapter.removeAll();
|
||||
return;
|
||||
}
|
||||
View emptyContentView = binding.activityNotesListView.emptyContentView.getRoot();
|
||||
emptyContentView.setVisibility(GONE);
|
||||
binding.activityNotesListView.progressCircular.setVisibility(VISIBLE);
|
||||
fabCreate.show();
|
||||
String subtitle;
|
||||
if (navigationSelection.category != null) {
|
||||
if (navigationSelection.category.isEmpty()) {
|
||||
subtitle = getString(R.string.search_in_category, getString(R.string.action_uncategorized));
|
||||
} else {
|
||||
subtitle = getString(R.string.search_in_category, NoteUtil.extendCategory(navigationSelection.category));
|
||||
}
|
||||
} else if (navigationSelection.favorite != null && navigationSelection.favorite) {
|
||||
subtitle = getString(R.string.search_in_category, getString(R.string.label_favorites));
|
||||
} else {
|
||||
subtitle = getString(R.string.search_in_all);
|
||||
}
|
||||
activityBinding.searchText.setText(subtitle);
|
||||
CharSequence query = null;
|
||||
if (activityBinding.searchView.getQuery().length() != 0) {
|
||||
query = activityBinding.searchView.getQuery();
|
||||
}
|
||||
// View emptyContentView = binding.activityNotesListView.emptyContentView.getRoot();
|
||||
// emptyContentView.setVisibility(GONE);
|
||||
// binding.activityNotesListView.progressCircular.setVisibility(VISIBLE);
|
||||
// fabCreate.show();
|
||||
// String subtitle;
|
||||
// if (navigationSelection.category != null) {
|
||||
// if (navigationSelection.category.isEmpty()) {
|
||||
// subtitle = getString(R.string.search_in_category, getString(R.string.action_uncategorized));
|
||||
// } else {
|
||||
// subtitle = getString(R.string.search_in_category, NoteUtil.extendCategory(navigationSelection.category));
|
||||
// }
|
||||
// } else if (navigationSelection.favorite != null && navigationSelection.favorite) {
|
||||
// subtitle = getString(R.string.search_in_category, getString(R.string.label_favorites));
|
||||
// } else {
|
||||
// subtitle = getString(R.string.search_in_all);
|
||||
// }
|
||||
// activityBinding.searchText.setText(subtitle);
|
||||
// CharSequence query = null;
|
||||
// if (activityBinding.searchView.getQuery().length() != 0) {
|
||||
// query = activityBinding.searchView.getQuery();
|
||||
// }
|
||||
|
||||
NotesLoadedListener callback = (List<Item> notes, boolean showCategory, CharSequence searchQuery) -> {
|
||||
adapter.setShowCategory(showCategory);
|
||||
adapter.setHighlightSearchQuery(searchQuery);
|
||||
adapter.setItemList(notes);
|
||||
binding.activityNotesListView.progressCircular.setVisibility(GONE);
|
||||
if (notes.size() > 0) {
|
||||
emptyContentView.setVisibility(GONE);
|
||||
} else {
|
||||
emptyContentView.setVisibility(VISIBLE);
|
||||
}
|
||||
if (scrollToTop) {
|
||||
listView.scrollToPosition(0);
|
||||
}
|
||||
};
|
||||
new LoadNotesListTask(localAccount.getId(), getApplicationContext(), callback, navigationSelection, query).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
// NotesLoadedListener callback = (List<Item> notes, boolean showCategory, CharSequence searchQuery) -> {
|
||||
// adapter.setShowCategory(showCategory);
|
||||
// adapter.setHighlightSearchQuery(searchQuery);
|
||||
// adapter.setItemList(notes);
|
||||
// binding.activityNotesListView.progressCircular.setVisibility(GONE);
|
||||
// if (notes.size() > 0) {
|
||||
// emptyContentView.setVisibility(GONE);
|
||||
// } else {
|
||||
// emptyContentView.setVisibility(VISIBLE);
|
||||
// }
|
||||
// if (scrollToTop) {
|
||||
// listView.scrollToPosition(0);
|
||||
// }
|
||||
// };
|
||||
// new LoadNotesListTask(localAccount.getId(), getApplicationContext(), callback, navigationSelection, query).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
updateSortMethodIcon(localAccount.getId());
|
||||
|
@ -984,6 +1002,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
|
|||
List<Account> remainingAccounts = db.getAccountDao().getAccounts();
|
||||
if (remainingAccounts.size() > 0) {
|
||||
this.localAccount = remainingAccounts.get(0);
|
||||
mainViewModel.postCurrentAccount(localAccount);
|
||||
selectAccount(this.localAccount.getAccountName());
|
||||
} else {
|
||||
selectAccount(null);
|
||||
|
|
|
@ -3,20 +3,25 @@ package it.niedermann.owncloud.notes.main;
|
|||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
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.Transformations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.Account;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory;
|
||||
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
|
||||
import it.niedermann.owncloud.notes.shared.model.Item;
|
||||
import it.niedermann.owncloud.notes.shared.model.OldCategory;
|
||||
|
||||
import static androidx.lifecycle.Transformations.distinctUntilChanged;
|
||||
import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByCategory;
|
||||
import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByInitials;
|
||||
import static it.niedermann.owncloud.notes.main.slots.SlotterUtil.fillListByTime;
|
||||
|
||||
public class MainViewModel extends AndroidViewModel {
|
||||
|
||||
|
@ -28,9 +33,7 @@ public class MainViewModel extends AndroidViewModel {
|
|||
@NonNull
|
||||
private MutableLiveData<String> searchTerm = new MutableLiveData<>();
|
||||
@NonNull
|
||||
private MutableLiveData<OldCategory> selectedCategory = new MutableLiveData<>();
|
||||
|
||||
private MediatorLiveData<List<Item>> notesListLiveData = new MediatorLiveData<>();
|
||||
private MutableLiveData<OldCategory> selectedCategory = new MutableLiveData<>(new OldCategory(null, null));
|
||||
|
||||
public MainViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
@ -49,6 +52,10 @@ public class MainViewModel extends AndroidViewModel {
|
|||
this.selectedCategory.postValue(selectedCategory);
|
||||
}
|
||||
|
||||
public LiveData<Account> getCurrentAccount() {
|
||||
return currentAccount;
|
||||
}
|
||||
|
||||
public LiveData<String> getSearchTerm() {
|
||||
return searchTerm;
|
||||
}
|
||||
|
@ -59,13 +66,44 @@ public class MainViewModel extends AndroidViewModel {
|
|||
|
||||
public LiveData<Void> filterChanged() {
|
||||
MediatorLiveData<Void> mediatorLiveData = new MediatorLiveData<>();
|
||||
mediatorLiveData.addSource(distinctUntilChanged(currentAccount), (o) -> mediatorLiveData.postValue(null));
|
||||
mediatorLiveData.addSource(distinctUntilChanged(searchTerm), (o) -> mediatorLiveData.postValue(null));
|
||||
mediatorLiveData.addSource(distinctUntilChanged(selectedCategory), (o) -> mediatorLiveData.postValue(null));
|
||||
mediatorLiveData.addSource(currentAccount, (o) -> mediatorLiveData.postValue(null));
|
||||
mediatorLiveData.addSource(searchTerm, (o) -> mediatorLiveData.postValue(null));
|
||||
mediatorLiveData.addSource(selectedCategory, (o) -> mediatorLiveData.postValue(null));
|
||||
return mediatorLiveData;
|
||||
}
|
||||
|
||||
public LiveData<List<Item>> getNotesListLiveData() {
|
||||
return notesListLiveData;
|
||||
Account currentAccount = getCurrentAccount().getValue();
|
||||
OldCategory selectedCategory = getSelectedCategory().getValue();
|
||||
LiveData<List<NoteWithCategory>> fromDatabase;
|
||||
if (currentAccount != null && selectedCategory != null) {
|
||||
Long accountId = currentAccount.getId();
|
||||
CategorySortingMethod sortingMethod = db.getCategoryOrder(accountId, selectedCategory);
|
||||
String searchQuery = getSearchTerm().getValue();
|
||||
searchQuery = searchQuery == null ? "%" : "%" + searchQuery.trim() + "%";
|
||||
if (Boolean.TRUE.equals(selectedCategory.favorite)) { // Favorites
|
||||
fromDatabase = db.getNoteDao().searchNotesFavorites(accountId, searchQuery, sortingMethod.getSorder());
|
||||
} else if (selectedCategory.category != null && selectedCategory.category.length() == 0) { // Uncategorized
|
||||
fromDatabase = db.getNoteDao().searchNotesUncategorized(accountId, searchQuery, sortingMethod.getSorder());
|
||||
} else if( selectedCategory.category == null && selectedCategory.favorite == null) { // Recent
|
||||
fromDatabase = db.getNoteDao().searchNotesAll(accountId, searchQuery, sortingMethod.getSorder());
|
||||
} else { // A special category
|
||||
fromDatabase = db.getNoteDao().searchNotesByCategory(accountId, searchQuery, selectedCategory.category, sortingMethod.getSorder());
|
||||
}
|
||||
|
||||
return Transformations.map(fromDatabase, (Function<List<NoteWithCategory>, List<Item>>) noteList -> {
|
||||
if (selectedCategory.category == null) {
|
||||
if (sortingMethod == CategorySortingMethod.SORT_MODIFIED_DESC) {
|
||||
return fillListByTime(getApplication(), noteList);
|
||||
} else {
|
||||
return fillListByInitials(getApplication(), noteList);
|
||||
}
|
||||
} else {
|
||||
return fillListByCategory(noteList, selectedCategory.category);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return new MutableLiveData<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package it.niedermann.owncloud.notes.main.slots;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.shared.model.Item;
|
||||
import it.niedermann.owncloud.notes.shared.util.NoteUtil;
|
||||
|
||||
public class SlotterUtil {
|
||||
|
||||
private SlotterUtil() {
|
||||
// Util class
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static List<Item> fillListByCategory(@NonNull List<NoteWithCategory> noteList, @Nullable String currentCategory) {
|
||||
List<Item> itemList = new ArrayList<>();
|
||||
for (NoteWithCategory note : noteList) {
|
||||
if (currentCategory != null && !currentCategory.equals(note.getCategory())) {
|
||||
itemList.add(new SectionItem(NoteUtil.extendCategory(note.getCategory())));
|
||||
}
|
||||
|
||||
itemList.add(note);
|
||||
currentCategory = note.getCategory();
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static List<Item> fillListByTime(@NonNull Context context, @NonNull List<NoteWithCategory> 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());
|
||||
if (i > 0 && !timeslot.equals(lastTimeslot)) {
|
||||
itemList.add(new SectionItem(timeslot));
|
||||
}
|
||||
itemList.add(currentNote);
|
||||
lastTimeslot = timeslot;
|
||||
}
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static List<Item> fillListByInitials(@NonNull Context context, @NonNull List<NoteWithCategory> noteList) {
|
||||
List<Item> itemList = new ArrayList<>();
|
||||
String lastInitials = null;
|
||||
for (int i = 0; i < noteList.size(); i++) {
|
||||
NoteWithCategory currentNote = noteList.get(i);
|
||||
String initials = currentNote.getNote().getTitle().substring(0, 1).toUpperCase();
|
||||
if (!initials.matches("[A-Z\\u00C0-\\u00DF]")) {
|
||||
initials = initials.matches("[\\u0250-\\uFFFF]") ? context.getString(R.string.simple_other) : "#";
|
||||
}
|
||||
if (i > 0 && !initials.equals(lastInitials)) {
|
||||
itemList.add(new SectionItem(initials));
|
||||
}
|
||||
itemList.add(currentNote);
|
||||
lastInitials = initials;
|
||||
}
|
||||
|
||||
return itemList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package it.niedermann.owncloud.notes.main.slots;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Timeslot {
|
||||
private final String label;
|
||||
private final Calendar time;
|
||||
|
||||
Timeslot(String label, int month, int day) {
|
||||
this.label = label;
|
||||
this.time = Calendar.getInstance();
|
||||
this.time.set(this.time.get(Calendar.YEAR), month, day, 0, 0, 0);
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public Calendar getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package it.niedermann.owncloud.notes.main.slots;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.Note;
|
||||
|
||||
public class Timeslotter {
|
||||
private final List<Timeslot> timeslots = new ArrayList<>();
|
||||
private final Calendar lastYear;
|
||||
private final Context context;
|
||||
|
||||
public Timeslotter(@NonNull Context context) {
|
||||
this.context = context;
|
||||
Calendar now = Calendar.getInstance();
|
||||
int month = now.get(Calendar.MONTH);
|
||||
int day = now.get(Calendar.DAY_OF_MONTH);
|
||||
int offsetWeekStart = (now.get(Calendar.DAY_OF_WEEK) - now.getFirstDayOfWeek() + 7) % 7;
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_today), month, day));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_yesterday), month, day - 1));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_this_week), month, day - offsetWeekStart));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_last_week), month, day - offsetWeekStart - 7));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_this_month), month, 1));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_last_month), month - 1, 1));
|
||||
lastYear = Calendar.getInstance();
|
||||
lastYear.set(now.get(Calendar.YEAR) - 1, 0, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
public String getTimeslot(Note note) {
|
||||
if (note.getFavorite()) {
|
||||
return "";
|
||||
}
|
||||
Calendar modified = note.getModified();
|
||||
for (Timeslot timeslot : timeslots) {
|
||||
if (!modified.before(timeslot.getTime())) {
|
||||
return timeslot.getLabel();
|
||||
}
|
||||
}
|
||||
if (!modified.before(this.lastYear)) {
|
||||
// use YEAR and MONTH in a format based on current locale
|
||||
return DateUtils.formatDateTime(context, modified.getTimeInMillis(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NO_MONTH_DAY);
|
||||
} else {
|
||||
return Integer.toString(modified.get(Calendar.YEAR));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,179 +1,75 @@
|
|||
package it.niedermann.owncloud.notes.persistence;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
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.Note;
|
||||
import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory;
|
||||
import it.niedermann.owncloud.notes.shared.model.OldCategory;
|
||||
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
|
||||
import it.niedermann.owncloud.notes.shared.model.Item;
|
||||
import it.niedermann.owncloud.notes.shared.util.NoteUtil;
|
||||
|
||||
public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
|
||||
|
||||
private final Context context;
|
||||
private final NotesLoadedListener callback;
|
||||
private final OldCategory category;
|
||||
private final String searchQuery;
|
||||
private final long accountId;
|
||||
|
||||
public LoadNotesListTask(long accountId, @NonNull Context context, @NonNull NotesLoadedListener callback, @NonNull OldCategory category, @Nullable CharSequence searchQuery) {
|
||||
this.context = context;
|
||||
this.callback = callback;
|
||||
this.category = category;
|
||||
this.searchQuery = searchQuery == null ? "%" : "%" + searchQuery + "%";
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Item> doInBackground(Void... voids) {
|
||||
List<NoteWithCategory> noteList;
|
||||
NotesDatabase db = NotesDatabase.getInstance(context);
|
||||
CategorySortingMethod sortingMethod = db.getCategoryOrder(accountId, category);
|
||||
|
||||
if(Boolean.TRUE.equals(category.favorite)) {
|
||||
noteList = db.getNoteDao().searchNotesByCategoryFavorites(accountId, searchQuery, sortingMethod);
|
||||
} else if(TextUtils.isEmpty(category.category)) {
|
||||
noteList = db.getNoteDao().searchNotesByUncategorized(accountId, searchQuery, sortingMethod);
|
||||
} else {
|
||||
noteList = db.getNoteDao().searchNotesByCategory(accountId, searchQuery, category.category, sortingMethod);
|
||||
}
|
||||
|
||||
if (category.category == null) {
|
||||
if (sortingMethod == CategorySortingMethod.SORT_MODIFIED_DESC) {
|
||||
return fillListByTime(noteList);
|
||||
} else {
|
||||
return fillListByInitials(noteList);
|
||||
}
|
||||
} else {
|
||||
return fillListByCategory(noteList);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@WorkerThread
|
||||
private List<Item> fillListByCategory(@NonNull List<NoteWithCategory> noteList) {
|
||||
List<Item> itemList = new ArrayList<>();
|
||||
String currentCategory = category.category;
|
||||
for (NoteWithCategory note : noteList) {
|
||||
if (currentCategory != null && !currentCategory.equals(note.getCategory())) {
|
||||
itemList.add(new SectionItem(NoteUtil.extendCategory(note.getCategory())));
|
||||
}
|
||||
|
||||
itemList.add(note);
|
||||
currentCategory = note.getCategory();
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@WorkerThread
|
||||
private List<Item> fillListByTime(@NonNull List<NoteWithCategory> noteList) {
|
||||
List<Item> itemList = new ArrayList<>();
|
||||
Timeslotter timeslotter = new Timeslotter();
|
||||
String lastTimeslot = null;
|
||||
for (int i = 0; i < noteList.size(); i++) {
|
||||
NoteWithCategory currentNote = noteList.get(i);
|
||||
String timeslot = timeslotter.getTimeslot(currentNote.getNote());
|
||||
if (i > 0 && !timeslot.equals(lastTimeslot)) {
|
||||
itemList.add(new SectionItem(timeslot));
|
||||
}
|
||||
itemList.add(currentNote);
|
||||
lastTimeslot = timeslot;
|
||||
}
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@WorkerThread
|
||||
private List<Item> fillListByInitials(@NonNull List<NoteWithCategory> noteList) {
|
||||
List<Item> itemList = new ArrayList<>();
|
||||
String lastInitials = null;
|
||||
for (int i = 0; i < noteList.size(); i++) {
|
||||
NoteWithCategory currentNote = noteList.get(i);
|
||||
String initials = currentNote.getNote().getTitle().substring(0, 1).toUpperCase();
|
||||
if (!initials.matches("[A-Z\\u00C0-\\u00DF]")) {
|
||||
initials = initials.matches("[\\u0250-\\uFFFF]") ? context.getString(R.string.simple_other) : "#";
|
||||
}
|
||||
if (i > 0 && !initials.equals(lastInitials)) {
|
||||
itemList.add(new SectionItem(initials));
|
||||
}
|
||||
itemList.add(currentNote);
|
||||
lastInitials = initials;
|
||||
}
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<Item> items) {
|
||||
callback.onNotesLoaded(items, category.category == null, searchQuery);
|
||||
}
|
||||
|
||||
public interface NotesLoadedListener {
|
||||
void onNotesLoaded(List<Item> notes, boolean showCategory, CharSequence searchQuery);
|
||||
}
|
||||
|
||||
private class Timeslotter {
|
||||
private final List<Timeslot> timeslots = new ArrayList<>();
|
||||
private final Calendar lastYear;
|
||||
|
||||
Timeslotter() {
|
||||
Calendar now = Calendar.getInstance();
|
||||
int month = now.get(Calendar.MONTH);
|
||||
int day = now.get(Calendar.DAY_OF_MONTH);
|
||||
int offsetWeekStart = (now.get(Calendar.DAY_OF_WEEK) - now.getFirstDayOfWeek() + 7) % 7;
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_today), month, day));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_yesterday), month, day - 1));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_this_week), month, day - offsetWeekStart));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_last_week), month, day - offsetWeekStart - 7));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_this_month), month, 1));
|
||||
timeslots.add(new Timeslot(context.getResources().getString(R.string.listview_updated_last_month), month - 1, 1));
|
||||
lastYear = Calendar.getInstance();
|
||||
lastYear.set(now.get(Calendar.YEAR) - 1, 0, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
private String getTimeslot(Note note) {
|
||||
if (note.getFavorite()) {
|
||||
return "";
|
||||
}
|
||||
Calendar modified = note.getModified();
|
||||
for (Timeslot timeslot : timeslots) {
|
||||
if (!modified.before(timeslot.time)) {
|
||||
return timeslot.label;
|
||||
}
|
||||
}
|
||||
if (!modified.before(this.lastYear)) {
|
||||
// use YEAR and MONTH in a format based on current locale
|
||||
return DateUtils.formatDateTime(context, modified.getTimeInMillis(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NO_MONTH_DAY);
|
||||
} else {
|
||||
return Integer.toString(modified.get(Calendar.YEAR));
|
||||
}
|
||||
}
|
||||
|
||||
private class Timeslot {
|
||||
private final String label;
|
||||
private final Calendar time;
|
||||
|
||||
Timeslot(String label, int month, int day) {
|
||||
this.label = label;
|
||||
this.time = Calendar.getInstance();
|
||||
this.time.set(this.time.get(Calendar.YEAR), month, day, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//package it.niedermann.owncloud.notes.persistence;
|
||||
//
|
||||
//import android.content.Context;
|
||||
//import android.os.AsyncTask;
|
||||
//import android.text.TextUtils;
|
||||
//import android.text.format.DateUtils;
|
||||
//
|
||||
//import androidx.annotation.NonNull;
|
||||
//import androidx.annotation.Nullable;
|
||||
//import androidx.annotation.WorkerThread;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.Calendar;
|
||||
//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.Note;
|
||||
//import it.niedermann.owncloud.notes.persistence.entity.NoteWithCategory;
|
||||
//import it.niedermann.owncloud.notes.shared.model.OldCategory;
|
||||
//import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
|
||||
//import it.niedermann.owncloud.notes.shared.model.Item;
|
||||
//import it.niedermann.owncloud.notes.shared.util.NoteUtil;
|
||||
//
|
||||
//public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
|
||||
//
|
||||
// private final Context context;
|
||||
// private final NotesLoadedListener callback;
|
||||
// private final OldCategory category;
|
||||
// private final String searchQuery;
|
||||
// private final long accountId;
|
||||
//
|
||||
// public LoadNotesListTask(long accountId, @NonNull Context context, @NonNull NotesLoadedListener callback, @NonNull OldCategory category, @Nullable CharSequence searchQuery) {
|
||||
// this.context = context;
|
||||
// this.callback = callback;
|
||||
// this.category = category;
|
||||
// this.searchQuery = searchQuery == null ? "%" : "%" + searchQuery + "%";
|
||||
// this.accountId = accountId;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected List<Item> doInBackground(Void... voids) {
|
||||
// List<NoteWithCategory> noteList;
|
||||
// NotesDatabase db = NotesDatabase.getInstance(context);
|
||||
// CategorySortingMethod sortingMethod = db.getCategoryOrder(accountId, category);
|
||||
//
|
||||
// if(Boolean.TRUE.equals(category.favorite)) {
|
||||
// noteList = db.getNoteDao().searchNotesByCategoryFavoritesDirectly(accountId, searchQuery, sortingMethod);
|
||||
// } else if(TextUtils.isEmpty(category.category)) {
|
||||
// noteList = db.getNoteDao().searchNotesByUncategorizedDirectly(accountId, searchQuery, sortingMethod);
|
||||
// } else {
|
||||
// noteList = db.getNoteDao().searchNotesByCategoryDirectly(accountId, searchQuery, category.category, sortingMethod);
|
||||
// }
|
||||
//
|
||||
//// if (category.category == null) {
|
||||
//// if (sortingMethod == CategorySortingMethod.SORT_MODIFIED_DESC) {
|
||||
//// return fillListByTime(noteList);
|
||||
//// } else {
|
||||
//// return fillListByInitials(noteList);
|
||||
//// }
|
||||
//// } else {
|
||||
//// return fillListByCategory(noteList);
|
||||
//// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onPostExecute(List<Item> items) {
|
||||
// callback.onNotesLoaded(items, category.category == null, searchQuery);
|
||||
// }
|
||||
//
|
||||
// public interface NotesLoadedListener {
|
||||
// void onNotesLoaded(List<Item> notes, boolean showCategory, CharSequence searchQuery);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
|
@ -366,7 +366,7 @@ public class NoteServerSyncHelper {
|
|||
switch (note.getStatus()) {
|
||||
case LOCAL_EDITED:
|
||||
Log.v(TAG, " ...create/edit");
|
||||
if (note.getRemoteId() > 0) {
|
||||
if (note.getRemoteId() != null && note.getRemoteId() > 0) {
|
||||
Log.v(TAG, " ...Note has remoteId → try to edit");
|
||||
try {
|
||||
remoteNote = notesClient.editNote(ssoAccount, note).getNote();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package it.niedermann.owncloud.notes.persistence.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.OnConflictStrategy;
|
||||
|
@ -31,15 +32,19 @@ public interface NoteDao {
|
|||
@Query("SELECT *, 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 OR CATEGORY.title LIKE :query) AND (CATEGORY.title = :category OR CATEGORY.title LIKE :category + '/%' " +
|
||||
") ORDER BY categoryId, favorite DESC, :sortingMethod")
|
||||
List<NoteWithCategory> searchNotesByCategory(long accountId, String query, String category, CategorySortingMethod sortingMethod);
|
||||
LiveData<List<NoteWithCategory>> searchNotesByCategory(long accountId, String query, String category, String sortingMethod);
|
||||
|
||||
@Query("SELECT *, 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 OR CATEGORY.title LIKE :query) AND favorite = 1 ORDER BY categoryId DESC, :sortingMethod")
|
||||
List<NoteWithCategory> searchNotesByCategoryFavorites(long accountId, String query, CategorySortingMethod sortingMethod);
|
||||
LiveData<List<NoteWithCategory>> searchNotesFavorites(long accountId, String query, String sortingMethod);
|
||||
|
||||
@Query("SELECT *, 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) OR CATEGORY.title = '' ORDER BY categoryId DESC, :sortingMethod")
|
||||
List<NoteWithCategory> searchNotesByUncategorized(long accountId, String query, CategorySortingMethod sortingMethod);
|
||||
"NOTE.title LIKE :query OR content LIKE :query) AND CATEGORY.title = '' ORDER BY categoryId DESC, :sortingMethod")
|
||||
LiveData<List<NoteWithCategory>> searchNotesUncategorized(long accountId, String query, String sortingMethod);
|
||||
|
||||
@Query("SELECT *, 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 OR CATEGORY.title LIKE :query) ORDER BY categoryId DESC, :sortingMethod")
|
||||
LiveData<List<NoteWithCategory>> searchNotesAll(long accountId, String query, String sortingMethod);
|
||||
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue