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 8a632dde..82cbdeb4 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 @@ -357,7 +357,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego @Override public void onCategoryChosen(String category) { - sqliteOpenHelperDatabase.setCategory(ssoAccount, note, category, null); + roomDatabase.setCategory(ssoAccount, note, category, null); listener.onNoteUpdated(note); } 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 28df5165..5822f2a7 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 @@ -1001,7 +1001,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V for (Integer i : new ArrayList<>(adapter.getSelected())) { DBNote note = (DBNote) adapter.getItem(i); note.setCategory(category); - sqliteOpenHelperDatabase.setCategory(ssoAccount, note, category, this::refreshLists); + roomDatabase.setCategory(ssoAccount, note, category, this::refreshLists); } mActionMode.finish(); 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 2b866027..5e207a9b 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 @@ -36,6 +36,7 @@ import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.BrandedSnackbar; import it.niedermann.owncloud.notes.exception.ExceptionDialogFragment; import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; +import it.niedermann.owncloud.notes.persistence.entity.NoteEntity; import it.niedermann.owncloud.notes.shared.model.CloudNote; import it.niedermann.owncloud.notes.shared.model.DBNote; import it.niedermann.owncloud.notes.shared.model.DBStatus; @@ -362,8 +363,9 @@ public class NoteServerSyncHelper { Log.d(TAG, "pushLocalChanges()"); boolean success = true; - List notes = sqliteOpenHelperDatabase.getLocalModifiedNotes(localAccount.getId()); - for (DBNote note : notes) { + List notes = roomDatabase.getNoteDao().getLocalModifiedNotes(localAccount.getId()); + for (NoteEntity noteEntity : notes) { + DBNote note = NoteEntity.entityToDBNote(noteEntity); Log.d(TAG, " Process Local Note: " + note); try { CloudNote remoteNote; @@ -518,7 +520,7 @@ public class NoteServerSyncHelper { } } sqliteOpenHelperDatabase.notifyWidgets(); - sqliteOpenHelperDatabase.updateDynamicShortcuts(localAccount.getId()); + roomDatabase.updateDynamicShortcuts(localAccount.getId()); // start next sync if scheduled meanwhile if (syncScheduled.containsKey(ssoAccount.name) && syncScheduled.get(ssoAccount.name) != null && Boolean.TRUE.equals(syncScheduled.get(ssoAccount.name))) { scheduleSync(ssoAccount, false); 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 1c187d95..34c50c62 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 @@ -262,19 +262,6 @@ public class NotesDatabase extends AbstractNotesDatabase { return getNotesCustom(accountId, TextUtils.join(" AND ", where), args.toArray(new String[]{}), order, true); } - /** - * Returns a list of all Notes in the Database which were modified locally - * - * @return {@link List} - */ - @NonNull - @WorkerThread - List getLocalModifiedNotes(long accountId) { - validateAccountId(accountId); - return getNotesCustom(accountId, key_status + " != ? AND " + key_account_id + " = ?", new String[]{DBStatus.VOID.getTitle(), "" + accountId}, null, false); - } - - /** * This method return all of the categories with given accountId * @@ -363,32 +350,6 @@ public class NotesDatabase extends AbstractNotesDatabase { serverSyncHelper.scheduleSync(ssoAccount, true); } - /** - * Set the category for a given note. - * This method will search in the database to find out the category id in the db. - * If there is no such category existing, this method will create it and search again. - * - * @param ssoAccount The single sign on account - * @param note The note which will be updated - * @param category The category title which should be used to find the category id. - * @param callback When the synchronization is finished, this callback will be invoked (optional). - */ - public void setCategory(SingleSignOnAccount ssoAccount, @NonNull DBNote note, @NonNull String category, @Nullable ISyncCallback callback) { - note.setCategory(category); - note.setStatus(DBStatus.LOCAL_EDITED); - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(2); - values.put(key_status, note.getStatus().getTitle()); - int id = getCategoryIdByTitle(note.getAccountId(), note.getCategory()); - values.put(key_category, id); - db.update(table_notes, values, key_id + " = ?", new String[]{String.valueOf(note.getId())}); - removeEmptyCategory(note.getAccountId()); - if (callback != null) { - serverSyncHelper.addCallbackPush(ssoAccount, callback); - } - serverSyncHelper.scheduleSync(ssoAccount, true); - } - private long addCategory(long accountId, @NonNull String title) { validateAccountId(accountId); SQLiteDatabase db = getWritableDatabase(); @@ -512,40 +473,6 @@ public class NotesDatabase extends AbstractNotesDatabase { updateNoteListWidgets(getContext()); } - void updateDynamicShortcuts(long accountId) { - new Thread(() -> { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) { - ShortcutManager shortcutManager = getContext().getApplicationContext().getSystemService(ShortcutManager.class); - if (shortcutManager != null) { - if (!shortcutManager.isRateLimitingActive()) { - List newShortcuts = new ArrayList<>(); - - for (DBNote note : getRecentNotes(accountId)) { - if (!TextUtils.isEmpty(note.getTitle())) { - Intent intent = new Intent(getContext().getApplicationContext(), EditNoteActivity.class); - intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId()); - intent.setAction(ACTION_SHORTCUT); - - newShortcuts.add(new ShortcutInfo.Builder(getContext().getApplicationContext(), note.getId() + "") - .setShortLabel(note.getTitle() + "") - .setIcon(Icon.createWithResource(getContext().getApplicationContext(), note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp)) - .setIntent(intent) - .build()); - } else { - // Prevent crash https://github.com/stefan-niedermann/nextcloud-notes/issues/613 - Log.e(TAG, "shortLabel cannot be empty " + note); - } - } - Log.d(TAG, "Update dynamic shortcuts"); - shortcutManager.removeAllDynamicShortcuts(); - shortcutManager.addDynamicShortcuts(newShortcuts); - } - } - } - }).start(); - } - - /** * @param apiVersion has to be a JSON array as a string ["0.2", "1.0", ...] * @return whether or not the given {@link ApiVersion} has been written to the database diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRoomDatabase.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRoomDatabase.java index a087fd34..d82d8f0b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRoomDatabase.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRoomDatabase.java @@ -1,11 +1,18 @@ package it.niedermann.owncloud.notes.persistence; +import android.content.ContentValues; import android.content.Context; +import android.content.Intent; +import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; +import android.database.sqlite.SQLiteDatabase; +import android.graphics.drawable.Icon; import android.os.Build; +import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import androidx.room.Database; import androidx.room.Room; @@ -16,9 +23,12 @@ import androidx.sqlite.db.SupportSQLiteDatabase; import com.nextcloud.android.sso.model.SingleSignOnAccount; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.edit.EditNoteActivity; import it.niedermann.owncloud.notes.persistence.dao.CategoryDao; import it.niedermann.owncloud.notes.persistence.dao.LocalAccountDao; import it.niedermann.owncloud.notes.persistence.dao.NoteDao; @@ -30,8 +40,10 @@ import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.model.CloudNote; import it.niedermann.owncloud.notes.shared.model.DBNote; import it.niedermann.owncloud.notes.shared.model.DBStatus; +import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.util.ColorUtil; +import static it.niedermann.owncloud.notes.edit.EditNoteActivity.ACTION_SHORTCUT; import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt; import static it.niedermann.owncloud.notes.widget.notelist.NoteListWidget.updateNoteListWidgets; import static it.niedermann.owncloud.notes.widget.singlenote.SingleNoteWidget.updateSingleNoteWidgets; @@ -251,4 +263,60 @@ public abstract class NotesRoomDatabase extends RoomDatabase { updateSingleNoteWidgets(context); updateNoteListWidgets(context); } + + + void updateDynamicShortcuts(long accountId) { + new Thread(() -> { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) { + ShortcutManager shortcutManager = context.getApplicationContext().getSystemService(ShortcutManager.class); + if (shortcutManager != null) { + if (!shortcutManager.isRateLimitingActive()) { + List newShortcuts = new ArrayList<>(); + + for (NoteEntity note : getNoteDao().getRecentNotes(accountId)) { + if (!TextUtils.isEmpty(note.getTitle())) { + Intent intent = new Intent(context.getApplicationContext(), EditNoteActivity.class); + intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId()); + intent.setAction(ACTION_SHORTCUT); + + newShortcuts.add(new ShortcutInfo.Builder(context.getApplicationContext(), note.getId() + "") + .setShortLabel(note.getTitle() + "") + .setIcon(Icon.createWithResource(context.getApplicationContext(), note.getFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp)) + .setIntent(intent) + .build()); + } else { + // Prevent crash https://github.com/stefan-niedermann/nextcloud-notes/issues/613 + Log.e(TAG, "shortLabel cannot be empty " + note); + } + } + Log.d(TAG, "Update dynamic shortcuts"); + shortcutManager.removeAllDynamicShortcuts(); + shortcutManager.addDynamicShortcuts(newShortcuts); + } + } + } + }).start(); + } + + /** + * Set the category for a given note. + * This method will search in the database to find out the category id in the db. + * If there is no such category existing, this method will create it and search again. + * + * @param ssoAccount The single sign on account + * @param note The note which will be updated + * @param category The category title which should be used to find the category id. + * @param callback When the synchronization is finished, this callback will be invoked (optional). + */ + public void setCategory(SingleSignOnAccount ssoAccount, @NonNull DBNote note, @NonNull String category, @Nullable ISyncCallback callback) { + note.setCategory(category); + getNoteDao().updateStatus(note.getId(), DBStatus.LOCAL_DELETED); + long categoryId = getOrCreateCategoryIdByTitle(note.getAccountId(), note.getCategory()); + getNoteDao().updateCategory(note.getId(), categoryId); + getCategoryDao().removeEmptyCategory(note.getAccountId()); + if (callback != null) { + syncHelper.addCallbackPush(ssoAccount, callback); + } + syncHelper.scheduleSync(ssoAccount, true); + } } 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 index 4dc4b2c9..1800fdf1 100644 --- 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 @@ -1,5 +1,8 @@ package it.niedermann.owncloud.notes.persistence.dao; +import android.content.ContentValues; +import android.database.sqlite.SQLiteDatabase; + import androidx.annotation.NonNull; import androidx.room.Dao; import androidx.room.Insert; @@ -27,4 +30,5 @@ public interface CategoryDao { @Query("SELECT id FROM CategoryEntity WHERE accountId = :accountId AND title = :title") Long getCategoryIdByTitle(long accountId, @NonNull String title); + } 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 136d1703..fdd95714 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 @@ -1,5 +1,7 @@ package it.niedermann.owncloud.notes.persistence.dao; +import androidx.annotation.NonNull; +import androidx.annotation.WorkerThread; import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; @@ -30,6 +32,9 @@ public interface NoteDao { @Query("UPDATE NoteEntity SET status = :status WHERE id = :id") void updateStatus(long id, DBStatus status); + @Query("UPDATE NoteEntity SET category_id = :categoryId WHERE id = :id") + void updateCategory(long id, long categoryId); + /** * Gets all the remoteIds of all not deleted notes of an account * @@ -51,4 +56,15 @@ public interface NoteDao { @Query("SELECT favorite, COUNT(*) FROM NoteEntity WHERE status != \"LOCAL_DELETED\" AND accountId = :accountId GROUP BY favorite ORDER BY favorite") Map getFavoritesCount(long accountId); + + /** + * Returns a list of all Notes in the Database which were modified locally + * + * @return {@link List} + */ + @Query("SELECT * FROM NoteEntity WHERE status != \"VOID\" AND accountId = :accountId") + List getLocalModifiedNotes(long accountId); + + @Query("SELECT * FROM NoteEntity WHERE status != \"LOCAL_DELETED\" AND accountId = :accountId ORDER BY modified DESC LIMIT 4") + List getRecentNotes(long accountId); }