diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-10-05 14:02:38 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-10-05 14:02:38 +0300 |
commit | 51bd8ff4642b4a697f204ea8170bfebe074f79c2 (patch) | |
tree | 6e2b5fb72e10aa2b76e92f105e4c85b39a11c81f /app/src/main/java/it/niedermann | |
parent | db0cf856540b2ca864865c7b9ac0d354905be37a (diff) |
#831 Migrate from SQLiteOpenHelper to Room
Diffstat (limited to 'app/src/main/java/it/niedermann')
22 files changed, 434 insertions, 337 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 23e68804..f2532b81 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/AppendToNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/AppendToNoteActivity.java @@ -36,7 +36,7 @@ public class AppendToNoteActivity extends MainActivity { @Override public void onNoteClick(int position, View v) { if (receivedText != null && receivedText.length() > 0) { - final DBNote note = db.getNote(localAccount.getId(), ((DBNote) adapter.getItem(position)).getId()); + final DBNote note = sqliteOpenHelperDatabase.getNote(localAccount.getId(), ((DBNote) adapter.getItem(position)).getId()); final String oldContent = note.getContent(); String newContent; if (oldContent != null && oldContent.length() > 0) { @@ -44,7 +44,7 @@ public class AppendToNoteActivity extends MainActivity { } else { newContent = receivedText; } - db.updateNoteAndSync(ssoAccount, localAccount, note, newContent, () -> Toast.makeText(this, getString(R.string.added_content, receivedText), Toast.LENGTH_SHORT).show()); + sqliteOpenHelperDatabase.updateNoteAndSync(ssoAccount, localAccount, note, newContent, () -> Toast.makeText(this, getString(R.string.added_content, receivedText), Toast.LENGTH_SHORT).show()); } else { Toast.makeText(this, R.string.shared_text_empty, Toast.LENGTH_SHORT).show(); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountpicker/AccountPickerDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/accountpicker/AccountPickerDialogFragment.java index 91011250..8ca0205c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/accountpicker/AccountPickerDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/accountpicker/AccountPickerDialogFragment.java @@ -22,6 +22,8 @@ import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder; import it.niedermann.owncloud.notes.branding.BrandedDialogFragment; import it.niedermann.owncloud.notes.databinding.DialogChooseAccountBinding; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import it.niedermann.owncloud.notes.persistence.NotesRoomDatabase; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.account.AccountChooserAdapter; import it.niedermann.owncloud.notes.shared.account.AccountChooserViewHolder; import it.niedermann.owncloud.notes.shared.model.LocalAccount; @@ -59,7 +61,7 @@ public class AccountPickerDialogFragment extends BrandedDialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final List<LocalAccount> accountsList = NotesDatabase.getInstance(getActivity()).getAccounts(); + final List<LocalAccountEntity> accountsList = NotesRoomDatabase.getInstance(getActivity()).getLocalAccountDao().getAccounts(); final AlertDialog.Builder dialogBuilder = new BrandedAlertDialogBuilder(requireActivity()) .setTitle(R.string.simple_move) .setNegativeButton(android.R.string.cancel, null); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java index 92e77e74..5488fd8d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java @@ -11,12 +11,15 @@ import java.util.ArrayList; import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.LocalAccount; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; + public class AccountSwitcherAdapter extends RecyclerView.Adapter<AccountSwitcherViewHolder> { @NonNull - private final List<LocalAccount> localAccounts = new ArrayList<>(); + private final List<LocalAccountEntity> localAccounts = new ArrayList<>(); @NonNull private final Consumer<LocalAccount> onAccountClick; @@ -38,7 +41,7 @@ public class AccountSwitcherAdapter extends RecyclerView.Adapter<AccountSwitcher @Override public void onBindViewHolder(@NonNull AccountSwitcherViewHolder holder, int position) { - holder.bind(localAccounts.get(position), onAccountClick); + holder.bind(entityToLocalAccount(localAccounts.get(position)), onAccountClick); } @Override @@ -46,7 +49,7 @@ public class AccountSwitcherAdapter extends RecyclerView.Adapter<AccountSwitcher return localAccounts.size(); } - public void setLocalAccounts(@NonNull List<LocalAccount> localAccounts) { + public void setLocalAccounts(@NonNull List<LocalAccountEntity> localAccounts) { this.localAccounts.clear(); this.localAccounts.addAll(localAccounts); notifyDataSetChanged(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java index 4286cf1e..75e55a1c 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java @@ -21,6 +21,8 @@ import it.niedermann.owncloud.notes.branding.BrandedDialogFragment; import it.niedermann.owncloud.notes.databinding.DialogAccountSwitcherBinding; import it.niedermann.owncloud.notes.manageaccounts.ManageAccountsActivity; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import it.niedermann.owncloud.notes.persistence.NotesRoomDatabase; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.LocalAccount; import static it.niedermann.owncloud.notes.branding.BrandingUtil.applyBrandToLayerDrawable; @@ -33,7 +35,8 @@ public class AccountSwitcherDialog extends BrandedDialogFragment { private static final String KEY_CURRENT_ACCOUNT_ID = "current_account_id"; - private NotesDatabase db; + private NotesDatabase sqliteOpenHelperDatabase; + private NotesRoomDatabase roomDatabase; private DialogAccountSwitcherBinding binding; private AccountSwitcherListener accountSwitcherListener; private long currentAccountId; @@ -55,7 +58,8 @@ public class AccountSwitcherDialog extends BrandedDialogFragment { this.currentAccountId = args.getLong(KEY_CURRENT_ACCOUNT_ID); } - db = NotesDatabase.getInstance(getActivity()); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(getActivity()); + roomDatabase = NotesRoomDatabase.getInstance(getActivity()); } @NonNull @@ -63,11 +67,11 @@ public class AccountSwitcherDialog extends BrandedDialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { binding = DialogAccountSwitcherBinding.inflate(requireActivity().getLayoutInflater()); - LocalAccount currentLocalAccount = db.getAccount(currentAccountId); - binding.accountName.setText(currentLocalAccount.getUserName()); + LocalAccountEntity currentLocalAccount = roomDatabase.getLocalAccountDao().getAccount(currentAccountId); + binding.accountName.setText(currentLocalAccount.getUsername()); binding.accountHost.setText(Uri.parse(currentLocalAccount.getUrl()).getHost()); Glide.with(requireContext()) - .load(currentLocalAccount.getUrl() + "/index.php/avatar/" + Uri.encode(currentLocalAccount.getUserName()) + "/64") + .load(currentLocalAccount.getUrl() + "/index.php/avatar/" + Uri.encode(currentLocalAccount.getUsername()) + "/64") .error(R.drawable.ic_account_circle_grey_24dp) .apply(RequestOptions.circleCropTransform()) .into(binding.currentAccountItemAvatar); @@ -78,8 +82,8 @@ public class AccountSwitcherDialog extends BrandedDialogFragment { dismiss(); })); binding.accountsList.setAdapter(adapter); - List<LocalAccount> localAccounts = db.getAccounts(); - for (LocalAccount localAccount : localAccounts) { + List<LocalAccountEntity> localAccounts = roomDatabase.getLocalAccountDao().getAccounts(); + for (LocalAccountEntity localAccount : localAccounts) { if (localAccount.getId() == currentLocalAccount.getId()) { localAccounts.remove(localAccount); break; 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 03625312..40f70c29 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 @@ -37,6 +37,8 @@ import it.niedermann.owncloud.notes.edit.category.CategoryDialogFragment.Categor import it.niedermann.owncloud.notes.edit.title.EditTitleDialogFragment; import it.niedermann.owncloud.notes.edit.title.EditTitleDialogFragment.EditTitleListener; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import it.niedermann.owncloud.notes.persistence.NotesRoomDatabase; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.ApiVersion; import it.niedermann.owncloud.notes.shared.model.CloudNote; import it.niedermann.owncloud.notes.shared.model.DBNote; @@ -51,6 +53,7 @@ import static androidx.core.content.pm.ShortcutManagerCompat.isRequestPinShortcu import static it.niedermann.owncloud.notes.NotesApplication.isDarkThemeActive; import static it.niedermann.owncloud.notes.branding.BrandingUtil.tintMenuIcon; import static it.niedermann.owncloud.notes.edit.EditNoteActivity.ACTION_SHORTCUT; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; import static it.niedermann.owncloud.notes.shared.util.ColorUtil.isColorDark; public abstract class BaseNoteFragment extends BrandedFragment implements CategoryDialogListener, EditTitleListener { @@ -65,7 +68,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego private static final String SAVEDKEY_NOTE = "note"; private static final String SAVEDKEY_ORIGINAL_NOTE = "original_note"; - private LocalAccount localAccount; + private LocalAccountEntity localAccountEntity; private SingleSignOnAccount ssoAccount; protected DBNote note; @@ -73,7 +76,8 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego @Nullable private DBNote originalNote; private int originalScrollY; - protected NotesDatabase db; + protected NotesDatabase sqliteOpenHelperDatabase; + protected NotesRoomDatabase roomDatabase; private NoteFragmentListener listener; private boolean titleModified = false; @@ -87,7 +91,8 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego } catch (ClassCastException e) { throw new ClassCastException(context.getClass() + " must implement " + NoteFragmentListener.class); } - db = NotesDatabase.getInstance(context); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(context); + roomDatabase = NotesRoomDatabase.getInstance(context); } @Override @@ -95,7 +100,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego super.onCreate(savedInstanceState); try { this.ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(requireActivity().getApplicationContext()); - this.localAccount = db.getLocalAccountByAccountName(ssoAccount.name); + this.localAccountEntity = roomDatabase.getLocalAccountDao().getLocalAccountByAccountName(ssoAccount.name); if (savedInstanceState == null) { long id = requireArguments().getLong(PARAM_NOTE_ID); @@ -103,11 +108,11 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego long accountId = requireArguments().getLong(PARAM_ACCOUNT_ID); if (accountId > 0) { /* Switch account if account id has been provided */ - this.localAccount = db.getAccount(accountId); - SingleAccountHelper.setCurrentAccount(requireActivity().getApplicationContext(), localAccount.getAccountName()); + this.localAccountEntity = roomDatabase.getLocalAccountDao().getAccount(accountId); + SingleAccountHelper.setCurrentAccount(requireActivity().getApplicationContext(), localAccountEntity.getAccountName()); } isNew = false; - note = originalNote = db.getNote(localAccount.getId(), id); + note = originalNote = sqliteOpenHelperDatabase.getNote(localAccountEntity.getId(), id); } else { CloudNote cloudNote = (CloudNote) requireArguments().getSerializable(PARAM_NEWNOTE); String content = requireArguments().getString(PARAM_CONTENT); @@ -118,7 +123,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego note = new DBNote(-1, -1, null, NoteUtil.generateNoteTitle(content), content, false, getString(R.string.category_readonly), null, DBStatus.VOID, -1, "", 0); } } else { - note = db.getNote(localAccount.getId(), db.addNoteAndSync(ssoAccount, localAccount.getId(), cloudNote)); + note = sqliteOpenHelperDatabase.getNote(localAccountEntity.getId(), sqliteOpenHelperDatabase.addNoteAndSync(ssoAccount, localAccountEntity.getId(), cloudNote)); originalNote = null; } } @@ -201,7 +206,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego MenuItem itemFavorite = menu.findItem(R.id.menu_favorite); prepareFavoriteOption(itemFavorite); - menu.findItem(R.id.menu_title).setVisible(localAccount.getPreferredApiVersion() != null && localAccount.getPreferredApiVersion().compareTo(new ApiVersion("1.0", 1, 0)) >= 0); + menu.findItem(R.id.menu_title).setVisible(localAccountEntity.getPreferredApiVersion() != null && localAccountEntity.getPreferredApiVersion().compareTo(new ApiVersion("1.0", 1, 0)) >= 0); menu.findItem(R.id.menu_delete).setVisible(!isNew); } @@ -219,18 +224,18 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego switch (item.getItemId()) { case R.id.menu_cancel: if (originalNote == null) { - db.deleteNoteAndSync(ssoAccount, note.getId()); + sqliteOpenHelperDatabase.deleteNoteAndSync(ssoAccount, note.getId()); } else { - db.updateNoteAndSync(ssoAccount, localAccount, originalNote, null, null); + sqliteOpenHelperDatabase.updateNoteAndSync(ssoAccount, entityToLocalAccount(localAccountEntity), originalNote, null, null); } listener.close(); return true; case R.id.menu_delete: - db.deleteNoteAndSync(ssoAccount, note.getId()); + sqliteOpenHelperDatabase.deleteNoteAndSync(ssoAccount, note.getId()); listener.close(); return true; case R.id.menu_favorite: - db.toggleFavorite(ssoAccount, note, null); + sqliteOpenHelperDatabase.toggleFavorite(ssoAccount, note, null); listener.onNoteUpdated(note); prepareFavoriteOption(item); return true; @@ -286,7 +291,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego public void onCloseNote() { if (!titleModified && originalNote == null && getContent().isEmpty()) { - db.deleteNoteAndSync(ssoAccount, note.getId()); + sqliteOpenHelperDatabase.deleteNoteAndSync(ssoAccount, note.getId()); } } @@ -302,12 +307,12 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego if (note.getContent().equals(newContent)) { if (note.getScrollY() != originalScrollY) { Log.v(TAG, "... only saving new scroll state, since content did not change"); - db.updateScrollY(note.getId(), note.getScrollY()); + sqliteOpenHelperDatabase.updateScrollY(note.getId(), note.getScrollY()); } else { Log.v(TAG, "... not saving, since nothing has changed"); } } else { - note = db.updateNoteAndSync(ssoAccount, localAccount, note, newContent, callback); + note = sqliteOpenHelperDatabase.updateNoteAndSync(ssoAccount, entityToLocalAccount(localAccountEntity), note, newContent, callback); listener.onNoteUpdated(note); requireActivity().invalidateOptionsMenu(); } @@ -351,7 +356,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego @Override public void onCategoryChosen(String category) { - db.setCategory(ssoAccount, note, category, null); + sqliteOpenHelperDatabase.setCategory(ssoAccount, note, category, null); listener.onNoteUpdated(note); } @@ -359,12 +364,12 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego public void onTitleEdited(String newTitle) { titleModified = true; note.setTitle(newTitle); - note = db.updateNoteAndSync(ssoAccount, localAccount, note, note.getContent(), newTitle, null); + note = sqliteOpenHelperDatabase.updateNoteAndSync(ssoAccount, entityToLocalAccount(localAccountEntity), note, note.getContent(), newTitle, null); listener.onNoteUpdated(note); } public void moveNote(LocalAccount account) { - db.moveNoteToAnotherAccount(ssoAccount, note.getAccountId(), note, account.getId()); + sqliteOpenHelperDatabase.moveNoteToAnotherAccount(ssoAccount, note.getAccountId(), note, account.getId()); listener.close(); } 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 9013438d..04af4a08 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 @@ -160,7 +160,7 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O .setOnLinkClickCallback((view, link) -> { if (NoteLinksUtils.isNoteLink(link)) { final Intent intent = new Intent(requireActivity().getApplicationContext(), EditNoteActivity.class) - .putExtra(EditNoteActivity.PARAM_NOTE_ID, db.getLocalIdByRemoteId(this.note.getAccountId(), extractNoteRemoteId(link))); + .putExtra(EditNoteActivity.PARAM_NOTE_ID, sqliteOpenHelperDatabase.getLocalIdByRemoteId(this.note.getAccountId(), extractNoteRemoteId(link))); startActivity(intent); } else { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link)); @@ -181,7 +181,7 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O changedText = note.getContent(); binding.singleNoteContent.setMovementMethod(LinkMovementMethod.getInstance()); - db = NotesDatabase.getInstance(requireContext()); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(requireContext()); binding.swiperefreshlayout.setOnRefreshListener(this); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(requireActivity().getApplicationContext()); @@ -207,18 +207,18 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O @Override public void onRefresh() { - if (db.getNoteServerSyncHelper().isSyncPossible() && SSOUtil.isConfigured(getContext())) { + if (sqliteOpenHelperDatabase.getNoteServerSyncHelper().isSyncPossible() && SSOUtil.isConfigured(getContext())) { binding.swiperefreshlayout.setRefreshing(true); try { TextProcessorChain chain = defaultTextProcessorChain(note); SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(requireContext()); - db.getNoteServerSyncHelper().addCallbackPull(ssoAccount, () -> { - note = db.getNote(note.getAccountId(), note.getId()); + sqliteOpenHelperDatabase.getNoteServerSyncHelper().addCallbackPull(ssoAccount, () -> { + note = sqliteOpenHelperDatabase.getNote(note.getAccountId(), note.getId()); changedText = note.getContent(); binding.singleNoteContent.setText(parseCompat(markdownProcessor, chain.apply(note.getContent()))); binding.swiperefreshlayout.setRefreshing(false); }); - db.getNoteServerSyncHelper().scheduleSync(ssoAccount, false); + sqliteOpenHelperDatabase.getNoteServerSyncHelper().scheduleSync(ssoAccount, false); } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { e.printStackTrace(); } @@ -236,7 +236,7 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O private TextProcessorChain defaultTextProcessorChain(DBNote note) { TextProcessorChain chain = new TextProcessorChain(); - chain.add(new NoteLinksProcessor(db.getRemoteIds(note.getAccountId()))); + chain.add(new NoteLinksProcessor(sqliteOpenHelperDatabase.getRemoteIds(note.getAccountId()))); chain.add(new WwwLinksProcessor()); return chain; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteReadonlyFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteReadonlyFragment.java index 3b5e4c6e..d9c2a38e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteReadonlyFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteReadonlyFragment.java @@ -105,7 +105,7 @@ public class NoteReadonlyFragment extends SearchableBaseNoteFragment { .setOnLinkClickCallback((view, link) -> { if (NoteLinksUtils.isNoteLink(link)) { long noteRemoteId = NoteLinksUtils.extractNoteRemoteId(link); - long noteLocalId = db.getLocalIdByRemoteId(this.note.getAccountId(), noteRemoteId); + long noteLocalId = sqliteOpenHelperDatabase.getLocalIdByRemoteId(this.note.getAccountId(), noteRemoteId); Intent intent = new Intent(requireActivity().getApplicationContext(), EditNoteActivity.class); intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, noteLocalId); startActivity(intent); @@ -126,7 +126,7 @@ public class NoteReadonlyFragment extends SearchableBaseNoteFragment { } binding.singleNoteContent.setMovementMethod(LinkMovementMethod.getInstance()); - db = NotesDatabase.getInstance(getActivity()); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(getActivity()); binding.swiperefreshlayout.setEnabled(false); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(requireActivity().getApplicationContext()); 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 85fa9d44..0d3176e3 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 @@ -95,6 +95,7 @@ import static android.view.View.VISIBLE; import static it.niedermann.owncloud.notes.NotesApplication.isDarkThemeActive; import static it.niedermann.owncloud.notes.NotesApplication.isGridViewEnabled; import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; import static it.niedermann.owncloud.notes.shared.util.ColorUtil.contrastRatioIsSufficient; import static it.niedermann.owncloud.notes.shared.util.SSOUtil.askForNewAccount; import static java.util.Arrays.asList; @@ -140,7 +141,8 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V protected ItemAdapter adapter; - protected NotesDatabase db = null; + protected NotesDatabase sqliteOpenHelperDatabase = null; + protected NotesRoomDatabase roomDatabase = null; private NavigationAdapter adapterCategories; private NavigationItem itemRecent; private NavigationItem itemFavorites; @@ -191,15 +193,15 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION); } - db = NotesDatabase.getInstance(this); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(this); + roomDatabase = NotesRoomDatabase.getInstance(this); gridView = isGridViewEnabled(); if (!gridView || isDarkThemeActive(this)) { activityBinding.activityNotesListView.setBackgroundColor(ContextCompat.getColor(this, R.color.primary)); } - NotesRoomDatabase db = NotesRoomDatabase.getInstance(this); - LocalAccountDao dao = db.getLocalAccountDao(); + LocalAccountDao dao = roomDatabase.getLocalAccountDao(); new Thread(() -> { List<LocalAccountEntity> localAccountEntities = dao.getAccounts(); Log.v("TEST", localAccountEntities.size() + " acs"); @@ -209,7 +211,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V setupNavigationMenu(); setupNotesList(); - new Thread(() -> canMoveNoteToAnotherAccounts = db.getAccountsCount() > 1).start(); + new Thread(() -> canMoveNoteToAnotherAccounts = roomDatabase.getLocalAccountDao().getAccountsCount() > 1).start(); } @Override @@ -221,9 +223,9 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V } } catch (NoCurrentAccountSelectedException | NextcloudFilesAppAccountNotFoundException e) { if (localAccount == null) { - List<LocalAccount> localAccounts = db.getAccounts(); + List<LocalAccountEntity> localAccounts = roomDatabase.getLocalAccountDao().getAccounts(); if (localAccounts.size() > 0) { - localAccount = localAccounts.get(0); + localAccount = entityToLocalAccount(localAccounts.get(0)); } } if (!notAuthorizedAccountHandled) { @@ -235,7 +237,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V refreshLists(); if (localAccount != null) { synchronize(); - db.getNoteServerSyncHelper().addCallbackPull(ssoAccount, syncCallBack); + sqliteOpenHelperDatabase.getNoteServerSyncHelper().addCallbackPull(ssoAccount, syncCallBack); } super.onResume(); } @@ -253,12 +255,12 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V private void selectAccount(String accountName) { fabCreate.hide(); SingleAccountHelper.setCurrentAccount(getApplicationContext(), accountName); - localAccount = db.getLocalAccountByAccountName(accountName); + localAccount = entityToLocalAccount(roomDatabase.getLocalAccountDao().getLocalAccountByAccountName(accountName)); if (localAccount != null) { try { BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor()); ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()); - new NotesListViewItemTouchHelper(ssoAccount, this, db, adapter, syncCallBack, this::refreshLists, swipeRefreshLayout, this, gridView) + new NotesListViewItemTouchHelper(ssoAccount, this, sqliteOpenHelperDatabase, adapter, syncCallBack, this::refreshLists, swipeRefreshLayout, this, gridView) .attachToRecyclerView(listView); synchronize(); } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { @@ -375,13 +377,12 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V final Capabilities capabilities; try { capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount, localAccount.getCapabilitiesETag()); - db.updateCapabilitiesETag(localAccount.getId(), capabilities.getETag()); - db.updateBrand(localAccount.getId(), capabilities); - db.updateBrand(localAccount.getId(), capabilities); + roomDatabase.getLocalAccountDao().updateCapabilitiesETag(localAccount.getId(), capabilities.getETag()); + roomDatabase.updateBrand(localAccount.getId(), capabilities); localAccount.setColor(Color.parseColor(capabilities.getColor())); localAccount.setTextColor(Color.parseColor(capabilities.getTextColor())); BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor()); - db.updateApiVersion(localAccount.getId(), capabilities.getApiVersion()); + sqliteOpenHelperDatabase.updateApiVersion(localAccount.getId(), capabilities.getApiVersion()); Log.i(TAG, capabilities.toString()); } catch (Exception e) { if (e instanceof NextcloudHttpRequestFailedException && ((NextcloudHttpRequestFailedException) e).getStatusCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { @@ -411,14 +412,14 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V activityBinding.sortingMethod.setOnClickListener((v) -> { CategorySortingMethod method; - method = db.getCategoryOrder(localAccount.getId(), navigationSelection); + method = sqliteOpenHelperDatabase.getCategoryOrder(localAccount.getId(), navigationSelection); if (method == CategorySortingMethod.SORT_LEXICOGRAPHICAL_ASC) { method = CategorySortingMethod.SORT_MODIFIED_DESC; } else { method = CategorySortingMethod.SORT_LEXICOGRAPHICAL_ASC; } - db.modifyCategoryOrder(localAccount.getId(), navigationSelection, method); + sqliteOpenHelperDatabase.modifyCategoryOrder(localAccount.getId(), navigationSelection, method); refreshLists(); updateSortMethodIcon(localAccount.getId()); }); @@ -521,7 +522,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V if (localAccount == null) { return new ArrayList<>(); } - List<CategoryNavigationItem> categories = db.getCategories(localAccount.getId()); + List<CategoryNavigationItem> categories = sqliteOpenHelperDatabase.getCategories(localAccount.getId()); if (!categories.isEmpty() && categories.get(0).label.isEmpty()) { itemUncategorized = categories.get(0); itemUncategorized.label = getString(R.string.action_uncategorized); @@ -530,7 +531,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V itemUncategorized = null; } - Map<String, Integer> favorites = db.getFavoritesCount(localAccount.getId()); + Map<String, Integer> favorites = sqliteOpenHelperDatabase.getFavoritesCount(localAccount.getId()); //noinspection ConstantConditions int numFavorites = favorites.containsKey("1") ? favorites.get("1") : 0; //noinspection ConstantConditions @@ -715,7 +716,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V * Updates sorting method icon. */ private void updateSortMethodIcon(long localAccountId) { - CategorySortingMethod method = db.getCategoryOrder(localAccountId, navigationSelection); + CategorySortingMethod method = sqliteOpenHelperDatabase.getCategoryOrder(localAccountId, navigationSelection); if (method == CategorySortingMethod.SORT_LEXICOGRAPHICAL_ASC) { activityBinding.sortingMethod.setImageResource(R.drawable.alphabetical_asc); activityBinding.sortingMethod.setContentDescription(getString(R.string.sort_last_modified)); @@ -787,7 +788,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V if (resultCode == RESULT_FIRST_USER) { selectAccount(null); } - new Thread(() -> canMoveNoteToAnotherAccounts = db.getAccountsCount() > 1).start(); + new Thread(() -> canMoveNoteToAnotherAccounts = roomDatabase.getLocalAccountDao().getAccountsCount() > 1).start(); break; } default: { @@ -799,8 +800,8 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V try { Log.i(TAG, "Refreshing capabilities for " + ssoAccount.name); final Capabilities capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount, null); - db.addAccount(ssoAccount.url, ssoAccount.userId, ssoAccount.name, capabilities); - new Thread(() -> canMoveNoteToAnotherAccounts = db.getAccountsCount() > 1).start(); + roomDatabase.addAccount(ssoAccount.url, ssoAccount.userId, ssoAccount.name, capabilities); + new Thread(() -> canMoveNoteToAnotherAccounts = roomDatabase.getLocalAccountDao().getAccountsCount() > 1).start(); Log.i(TAG, capabilities.toString()); runOnUiThread(() -> selectAccount(ssoAccount.name)); } catch (SQLiteException e) { @@ -808,7 +809,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V runOnUiThread(() -> selectAccount(ssoAccount.name)); } catch (Exception e) { // Happens when importing an already existing account the second time - if (e instanceof TokenMismatchException && db.getLocalAccountByAccountName(ssoAccount.name) != null) { + if (e instanceof TokenMismatchException && roomDatabase.getLocalAccountDao().getLocalAccountByAccountName(ssoAccount.name) != null) { Log.w(TAG, "Received " + TokenMismatchException.class.getSimpleName() + " and the given ssoAccount.name (" + ssoAccount.name + ") does already exist in the database. Assume that this account has already been imported."); runOnUiThread(() -> { selectAccount(ssoAccount.name); @@ -895,7 +896,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V if (selected) { v.setSelected(true); mActionMode = startSupportActionMode(new MultiSelectedActionModeCallback( - this, this, db, localAccount.getId(), canMoveNoteToAnotherAccounts, adapter, listView, this::refreshLists, getSupportFragmentManager(), activityBinding.searchView + this, this, sqliteOpenHelperDatabase, localAccount.getId(), canMoveNoteToAnotherAccounts, adapter, listView, this::refreshLists, getSupportFragmentManager(), activityBinding.searchView )); int checkedItemCount = adapter.getSelected().size(); mActionMode.setTitle(getResources().getQuantityString(R.plurals.ab_selected, checkedItemCount, checkedItemCount)); @@ -929,7 +930,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V } private void synchronize() { - NoteServerSyncHelper syncHelper = db.getNoteServerSyncHelper(); + NoteServerSyncHelper syncHelper = sqliteOpenHelperDatabase.getNoteServerSyncHelper(); if (!syncHelper.isSyncPossible()) { syncHelper.updateNetworkStatus(); } @@ -961,11 +962,11 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V @Override public void onAccountDeleted(LocalAccount localAccount) { - db.deleteAccount(localAccount); + sqliteOpenHelperDatabase.deleteAccount(localAccount); if (localAccount.getId() == this.localAccount.getId()) { - List<LocalAccount> remainingAccounts = db.getAccounts(); + List<LocalAccountEntity> remainingAccounts = roomDatabase.getLocalAccountDao().getAccounts(); if (remainingAccounts.size() > 0) { - this.localAccount = remainingAccounts.get(0); + this.localAccount = entityToLocalAccount(remainingAccounts.get(0)); selectAccount(this.localAccount.getAccountName()); } else { selectAccount(null); @@ -981,7 +982,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V adapter.deselect(0); for (Integer i : selection) { DBNote note = (DBNote) adapter.getItem(i); - db.moveNoteToAnotherAccount(ssoAccount, note.getAccountId(), db.getNote(note.getAccountId(), note.getId()), account.getId()); + sqliteOpenHelperDatabase.moveNoteToAnotherAccount(ssoAccount, note.getAccountId(), sqliteOpenHelperDatabase.getNote(note.getAccountId(), note.getId()), account.getId()); RecyclerView.ViewHolder viewHolder = listView.findViewHolderForAdapterPosition(i); if (viewHolder != null) { viewHolder.itemView.setSelected(false); @@ -999,7 +1000,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); - db.setCategory(ssoAccount, note, category, this::refreshLists); + sqliteOpenHelperDatabase.setCategory(ssoAccount, note, category, this::refreshLists); } mActionMode.finish(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java index 33156fb6..f02a1581 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java @@ -12,14 +12,17 @@ import java.util.ArrayList; import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.LocalAccount; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; + public class ManageAccountAdapter extends RecyclerView.Adapter<ManageAccountViewHolder> { @Nullable private LocalAccount currentLocalAccount = null; @NonNull - private final List<LocalAccount> localAccounts = new ArrayList<>(); + private final List<LocalAccountEntity> localAccounts = new ArrayList<>(); @NonNull private final Consumer<LocalAccount> onAccountClick; @Nullable @@ -44,8 +47,8 @@ public class ManageAccountAdapter extends RecyclerView.Adapter<ManageAccountView @Override public void onBindViewHolder(@NonNull ManageAccountViewHolder holder, int position) { - final LocalAccount localAccount = localAccounts.get(position); - holder.bind(localAccount, (localAccountClicked) -> { + final LocalAccountEntity localAccount = localAccounts.get(position); + holder.bind(entityToLocalAccount(localAccount), (localAccountClicked) -> { setCurrentLocalAccount(localAccountClicked); onAccountClick.accept(localAccountClicked); }, (localAccountToDelete -> { @@ -67,7 +70,7 @@ public class ManageAccountAdapter extends RecyclerView.Adapter<ManageAccountView return localAccounts.size(); } - public void setLocalAccounts(@NonNull List<LocalAccount> localAccounts) { + public void setLocalAccounts(@NonNull List<LocalAccountEntity> localAccounts) { this.localAccounts.clear(); this.localAccounts.addAll(localAccounts); notifyDataSetChanged(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java index 7cf64230..73a2fbc6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java @@ -14,14 +14,19 @@ import java.util.List; import it.niedermann.owncloud.notes.LockedActivity; import it.niedermann.owncloud.notes.databinding.ActivityManageAccountsBinding; +import it.niedermann.owncloud.notes.persistence.NotesRoomDatabase; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.LocalAccount; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; + public class ManageAccountsActivity extends LockedActivity { private ActivityManageAccountsBinding binding; private ManageAccountAdapter adapter; - private NotesDatabase db = null; + private NotesDatabase sqliteOpenHelperDatabase = null; + private NotesRoomDatabase roomDatabase = null; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -32,13 +37,14 @@ public class ManageAccountsActivity extends LockedActivity { setSupportActionBar(binding.toolbar); - db = NotesDatabase.getInstance(this); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(this); + roomDatabase = NotesRoomDatabase.getInstance(this); - List<LocalAccount> localAccounts = db.getAccounts(); + List<LocalAccountEntity> localAccounts = roomDatabase.getLocalAccountDao().getAccounts(); adapter = new ManageAccountAdapter((localAccount) -> SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccount.getAccountName()), (localAccount) -> { - db.deleteAccount(localAccount); - for (LocalAccount temp : localAccounts) { + sqliteOpenHelperDatabase.deleteAccount(localAccount); + for (LocalAccountEntity temp : localAccounts) { if (temp.getId() == localAccount.getId()) { localAccounts.remove(temp); break; @@ -46,7 +52,7 @@ public class ManageAccountsActivity extends LockedActivity { } if (localAccounts.size() > 0) { SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccounts.get(0).getAccountName()); - adapter.setCurrentLocalAccount(localAccounts.get(0)); + adapter.setCurrentLocalAccount(entityToLocalAccount(localAccounts.get(0))); } else { setResult(AppCompatActivity.RESULT_FIRST_USER); finish(); @@ -56,7 +62,7 @@ public class ManageAccountsActivity extends LockedActivity { try { SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this); if (ssoAccount != null) { - adapter.setCurrentLocalAccount(db.getLocalAccountByAccountName(ssoAccount.name)); + adapter.setCurrentLocalAccount(entityToLocalAccount(roomDatabase.getLocalAccountDao().getLocalAccountByAccountName(ssoAccount.name))); } } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { e.printStackTrace(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesWorker.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesWorker.java index 26e18311..e0925188 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesWorker.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesWorker.java @@ -20,6 +20,7 @@ import java.net.HttpURLConnection; import java.util.Objects; import java.util.concurrent.TimeUnit; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.model.LocalAccount; @@ -42,15 +43,16 @@ public class CapabilitiesWorker extends Worker { @NonNull @Override public Result doWork() { - final NotesDatabase db = NotesDatabase.getInstance(getApplicationContext()); - for (LocalAccount account : db.getAccounts()) { + final NotesDatabase sqliteOpenHelperDatabase = NotesDatabase.getInstance(getApplicationContext()); + final NotesRoomDatabase roomDatabase = NotesRoomDatabase.getInstance(getApplicationContext()); + for (LocalAccountEntity account : roomDatabase.getLocalAccountDao().getAccounts()) { try { final SingleSignOnAccount ssoAccount = AccountImporter.getSingleSignOnAccount(getApplicationContext(), account.getAccountName()); Log.i(TAG, "Refreshing capabilities for " + ssoAccount.name); final Capabilities capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount, account.getCapabilitiesETag()); - db.updateCapabilitiesETag(account.getId(), capabilities.getETag()); - db.updateBrand(account.getId(), capabilities); - db.updateApiVersion(account.getId(), capabilities.getApiVersion()); + roomDatabase.getLocalAccountDao().updateCapabilitiesETag(account.getId(), capabilities.getETag()); + roomDatabase.updateBrand(account.getId(), capabilities); + sqliteOpenHelperDatabase.updateApiVersion(account.getId(), capabilities.getApiVersion()); Log.i(TAG, capabilities.toString()); } catch (Exception e) { if (e instanceof NextcloudHttpRequestFailedException) { 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 da8feb47..f27c018e 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 @@ -17,7 +17,6 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.preference.PreferenceManager; import com.google.android.material.snackbar.Snackbar; -import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException; @@ -34,17 +33,19 @@ import java.util.Objects; import java.util.Set; import it.niedermann.owncloud.notes.R; -import it.niedermann.owncloud.notes.exception.ExceptionDialogFragment; 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.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.model.LocalAccount; +import it.niedermann.owncloud.notes.shared.model.ServerResponse; import it.niedermann.owncloud.notes.shared.model.SyncResultStatus; import it.niedermann.owncloud.notes.shared.util.SSOUtil; -import it.niedermann.owncloud.notes.shared.model.ServerResponse; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED; @@ -57,7 +58,8 @@ public class NoteServerSyncHelper { private static NoteServerSyncHelper instance; - private final NotesDatabase db; + private final NotesDatabase sqliteOpenHelperDatabase; + private final NotesRoomDatabase roomDatabase; private final Context context; // Track network connection changes using a BroadcastReceiver @@ -99,9 +101,10 @@ public class NoteServerSyncHelper { private final Map<String, List<ISyncCallback>> callbacksPush = new HashMap<>(); private final Map<String, List<ISyncCallback>> callbacksPull = new HashMap<>(); - private NoteServerSyncHelper(NotesDatabase db) { - this.db = db; - this.context = db.getContext(); + private NoteServerSyncHelper(NotesDatabase sqliteOpenHelperDatabase, NotesRoomDatabase roomDatabase) { + this.sqliteOpenHelperDatabase = sqliteOpenHelperDatabase; + this.roomDatabase = roomDatabase; + this.context = sqliteOpenHelperDatabase.getContext(); this.syncOnlyOnWifiKey = context.getApplicationContext().getResources().getString(R.string.pref_key_wifi_only); // Registers BroadcastReceiver to track network connection changes. @@ -119,12 +122,12 @@ public class NoteServerSyncHelper { * This has to be a singleton in order to realize correct registering and unregistering of * the BroadcastReceiver, which listens on changes of network connectivity. * - * @param dbHelper NoteSQLiteOpenHelper + * @param sqliteOpenHelperDatabase NoteSQLiteOpenHelper * @return NoteServerSyncHelper */ - public static synchronized NoteServerSyncHelper getInstance(NotesDatabase dbHelper) { + public static synchronized NoteServerSyncHelper getInstance(NotesDatabase sqliteOpenHelperDatabase, NotesRoomDatabase roomDatabase) { if (instance == null) { - instance = new NoteServerSyncHelper(dbHelper); + instance = new NoteServerSyncHelper(sqliteOpenHelperDatabase, roomDatabase); } return instance; } @@ -215,13 +218,13 @@ public class NoteServerSyncHelper { Log.d(TAG, "Sync requested (" + (onlyLocalChanges ? "onlyLocalChanges" : "full") + "; " + (Boolean.TRUE.equals(syncActive.get(ssoAccount.name)) ? "sync active" : "sync NOT active") + ") ..."); if (isSyncPossible() && (!Boolean.TRUE.equals(syncActive.get(ssoAccount.name)) || onlyLocalChanges)) { Log.d(TAG, "... starting now"); - final LocalAccount localAccount = db.getLocalAccountByAccountName(ssoAccount.name); + final LocalAccountEntity localAccount = roomDatabase.getLocalAccountDao().getLocalAccountByAccountName(ssoAccount.name); if (localAccount == null) { - Log.e(TAG, LocalAccount.class.getSimpleName() + " for ssoAccount \"" + ssoAccount.name + "\" is null. Cannot synchronize.", new IllegalStateException()); + Log.e(TAG, LocalAccountEntity.class.getSimpleName() + " for ssoAccount \"" + ssoAccount.name + "\" is null. Cannot synchronize.", new IllegalStateException()); return; } final NotesClient notesClient = NotesClient.newInstance(localAccount.getPreferredApiVersion(), context); - final SyncTask syncTask = new SyncTask(notesClient, localAccount, ssoAccount, onlyLocalChanges); + final SyncTask syncTask = new SyncTask(notesClient, entityToLocalAccount(localAccount), ssoAccount, onlyLocalChanges); syncTask.addCallbacks(ssoAccount, callbacksPush.get(ssoAccount.name)); callbacksPush.put(ssoAccount.name, new ArrayList<>()); if (!onlyLocalChanges) { @@ -359,7 +362,7 @@ public class NoteServerSyncHelper { Log.d(TAG, "pushLocalChanges()"); boolean success = true; - List<DBNote> notes = db.getLocalModifiedNotes(localAccount.getId()); + List<DBNote> notes = sqliteOpenHelperDatabase.getLocalModifiedNotes(localAccount.getId()); for (DBNote note : notes) { Log.d(TAG, " Process Local Note: " + note); try { @@ -384,7 +387,7 @@ public class NoteServerSyncHelper { remoteNote = notesClient.createNote(ssoAccount, note).getNote(); } // Please note, that db.updateNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI. - db.updateNote(localAccount, note.getId(), remoteNote, note); + sqliteOpenHelperDatabase.updateNote(localAccount, note.getId(), remoteNote, note); break; case LOCAL_DELETED: if (note.getRemoteId() > 0) { @@ -402,7 +405,7 @@ public class NoteServerSyncHelper { Log.v(TAG, " ...delete (only local, since it has never been synchronized)"); } // Please note, that db.deleteNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI. - db.deleteNote(note.getId(), DBStatus.LOCAL_DELETED); + sqliteOpenHelperDatabase.deleteNote(note.getId(), DBStatus.LOCAL_DELETED); break; default: throw new IllegalStateException("Unknown State of Note: " + note); @@ -431,7 +434,7 @@ public class NoteServerSyncHelper { private boolean pullRemoteChanges() { Log.d(TAG, "pullRemoteChanges() for account " + localAccount.getAccountName()); try { - final Map<Long, Long> idMap = db.getIdMap(localAccount.getId()); + final Map<Long, Long> idMap = sqliteOpenHelperDatabase.getIdMap(localAccount.getId()); final ServerResponse.NotesResponse response = notesClient.getNotes(ssoAccount, localAccount.getModified(), localAccount.getEtag()); List<CloudNote> remoteNotes = response.getNotes(); Set<Long> remoteIDs = new HashSet<>(); @@ -445,13 +448,13 @@ public class NoteServerSyncHelper { Log.v(TAG, " ... found → Update"); Long remoteId = idMap.get(remoteNote.getRemoteId()); if (remoteId != null) { - db.updateNote(localAccount, remoteId, remoteNote, null); + sqliteOpenHelperDatabase.updateNote(localAccount, remoteId, remoteNote, null); } else { Log.e(TAG, "Tried to update note from server, but remoteId of note is null. " + remoteNote); } } else { Log.v(TAG, " ... create"); - db.addNote(localAccount.getId(), remoteNote); + sqliteOpenHelperDatabase.addNote(localAccount.getId(), remoteNote); } } Log.d(TAG, " Remove remotely deleted Notes (only those without local changes)"); @@ -459,17 +462,17 @@ public class NoteServerSyncHelper { for (Map.Entry<Long, Long> entry : idMap.entrySet()) { if (!remoteIDs.contains(entry.getKey())) { Log.v(TAG, " ... remove " + entry.getValue()); - db.deleteNote(entry.getValue(), DBStatus.VOID); + sqliteOpenHelperDatabase.deleteNote(entry.getValue(), DBStatus.VOID); } } // update ETag and Last-Modified in order to reduce size of next response localAccount.setETag(response.getETag()); localAccount.setModified(response.getLastModified()); - db.updateETag(localAccount.getId(), localAccount.getEtag()); - db.updateModified(localAccount.getId(), localAccount.getModified()); + roomDatabase.getLocalAccountDao().updateETag(localAccount.getId(), localAccount.getEtag()); + roomDatabase.getLocalAccountDao().updateModified(localAccount.getId(), localAccount.getModified()); try { - if (db.updateApiVersion(localAccount.getId(), response.getSupportedApiVersions())) { + if (sqliteOpenHelperDatabase.updateApiVersion(localAccount.getId(), response.getSupportedApiVersions())) { localAccount.setPreferredApiVersion(response.getSupportedApiVersions()); } } catch (Exception e) { @@ -514,8 +517,8 @@ public class NoteServerSyncHelper { callback.onFinish(); } } - db.notifyWidgets(); - db.updateDynamicShortcuts(localAccount.getId()); + sqliteOpenHelperDatabase.notifyWidgets(); + sqliteOpenHelperDatabase.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 17b6928d..cf5495d7 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 @@ -80,7 +80,7 @@ public class NotesDatabase extends AbstractNotesDatabase { private NotesDatabase(@NonNull Context context) { super(context, database_name, null); - serverSyncHelper = NoteServerSyncHelper.getInstance(this); + serverSyncHelper = NoteServerSyncHelper.getInstance(this, NotesRoomDatabase.getInstance(context)); } public static NotesDatabase getInstance(Context context) { @@ -726,142 +726,6 @@ public class NotesDatabase extends AbstractNotesDatabase { }).start(); } - public long getAccountsCount() { - return DatabaseUtils.queryNumEntries(getReadableDatabase(), table_accounts); - } - - /** - * @param url URL to the root of the used Nextcloud instance without trailing slash - * @param username Username of the account - * @param accountName Composed by the username and the host of the URL, separated by @-sign - * @param capabilities {@link Capabilities} object containing information about the brand colors, supported API versions, etc... - * @throws SQLiteConstraintException in case accountName already exists - */ - public void addAccount(@NonNull String url, @NonNull String username, @NonNull String accountName, @NonNull Capabilities capabilities) throws SQLiteConstraintException { - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(4); - values.put(key_url, url); - values.put(key_username, username); - values.put(key_account_name, accountName); - values.put(key_capabilities_etag, capabilities.getETag()); - long accountId = db.insertOrThrow(table_accounts, null, values); - updateBrand(accountId, capabilities); - } - - /** - * @param accountId account which should be read - * @return a {@link LocalAccount} object for the given accountId - */ - public LocalAccount getAccount(long accountId) { - validateAccountId(accountId); - final SQLiteDatabase db = getReadableDatabase(); - final Cursor cursor = db.query(table_accounts, new String[]{key_id, key_url, key_account_name, key_username, key_etag, key_modified, key_api_version, key_color, key_text_color, key_capabilities_etag}, key_id + " = ?", new String[]{String.valueOf(accountId)}, null, null, null, null); - final LocalAccount account = new LocalAccount(); - while (cursor.moveToNext()) { - account.setId(cursor.getLong(0)); - account.setUrl(cursor.getString(1)); - account.setAccountName(cursor.getString(2)); - account.setUserName(cursor.getString(3)); - account.setETag(cursor.getString(4)); - account.setModified(cursor.getLong(5)); - account.setPreferredApiVersion(cursor.getString(6)); - account.setColor(Color.parseColor('#' + cursor.getString(7))); - account.setTextColor(Color.parseColor('#' + cursor.getString(8))); - account.setCapabilitiesETag(cursor.getString(9)); - } - cursor.close(); - return account; - } - - @NonNull - public List<LocalAccount> getAccounts() { - final SQLiteDatabase db = getReadableDatabase(); - final Cursor cursor = db.query(table_accounts, new String[]{key_id, key_url, key_account_name, key_username, key_etag, key_modified, key_api_version, key_color, key_text_color, key_capabilities_etag}, null, null, null, null, null); - final List<LocalAccount> accounts = new ArrayList<>(cursor.getCount()); - while (cursor.moveToNext()) { - LocalAccount account = new LocalAccount(); - account.setId(cursor.getLong(0)); - account.setUrl(cursor.getString(1)); - account.setAccountName(cursor.getString(2)); - account.setUserName(cursor.getString(3)); - account.setETag(cursor.getString(4)); - account.setModified(cursor.getLong(5)); - account.setPreferredApiVersion(cursor.getString(6)); - account.setColor(Color.parseColor('#' + cursor.getString(7))); - account.setTextColor(Color.parseColor('#' + cursor.getString(8))); - account.setCapabilitiesETag(cursor.getString(9)); - accounts.add(account); - } - cursor.close(); - return accounts; - } - - @Nullable - public LocalAccount getLocalAccountByAccountName(String accountName) throws IllegalArgumentException { - if (accountName == null) { - Log.e(TAG, "accountName is null"); - return null; - } - final SQLiteDatabase db = getReadableDatabase(); - final Cursor cursor = db.query(table_accounts, new String[]{key_id, key_url, key_account_name, key_username, key_etag, key_modified, key_api_version, key_color, key_text_color, key_capabilities_etag}, key_account_name + " = ?", new String[]{accountName}, null, null, null, null); - final LocalAccount account = new LocalAccount(); - int numberEntries = 0; - while (cursor.moveToNext()) { - numberEntries++; - account.setId(cursor.getLong(0)); - account.setUrl(cursor.getString(1)); - account.setAccountName(cursor.getString(2)); - account.setUserName(cursor.getString(3)); - account.setETag(cursor.getString(4)); - account.setModified(cursor.getLong(5)); - account.setPreferredApiVersion(cursor.getString(6)); - account.setColor(Color.parseColor('#' + cursor.getString(7))); - account.setTextColor(Color.parseColor('#' + cursor.getString(8))); - account.setCapabilitiesETag(cursor.getString(9)); - } - cursor.close(); - switch (numberEntries) { - case 0: - Log.w(TAG, "Could not find any account for \"" + accountName + "\". Returning null."); - return null; - case 1: - return account; - default: - Log.e(TAG, "", new IllegalArgumentException("Expected to find 1 account for name \"" + accountName + "\", but found " + numberEntries + ".")); - return null; - } - } - - public void updateBrand(long accountId, @NonNull Capabilities capabilities) throws IllegalArgumentException { - validateAccountId(accountId); - - String color; - try { - color = ColorUtil.formatColorToParsableHexString(capabilities.getColor()).substring(1); - } catch (Exception e) { - color = String.format("%06X", (0xFFFFFF & ContextCompat.getColor(context, R.color.defaultBrand))); - } - - String textColor; - try { - textColor = ColorUtil.formatColorToParsableHexString(capabilities.getTextColor()).substring(1); - } catch (Exception e) { - textColor = String.format("%06X", (0xFFFFFF & ContextCompat.getColor(context, android.R.color.white))); - } - - final SQLiteDatabase db = this.getWritableDatabase(); - final ContentValues values = new ContentValues(2); - - values.put(key_color, color); - values.put(key_text_color, textColor); - - final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{String.valueOf(accountId)}); - if (updatedRows == 1) { - Log.v(TAG, "Updated " + key_color + " to " + capabilities.getColor() + " and " + key_text_color + " to " + capabilities.getTextColor() + " for " + key_account_id + " = " + accountId); - } else { - Log.e(TAG, "Updated " + updatedRows + " but expected only 1 for accountId = " + accountId + " and " + key_color + " = " + capabilities.getColor() + " and " + key_text_color + " = " + capabilities.getTextColor()); - } - } /** * @param apiVersion has to be a JSON array as a string <code>["0.2", "1.0", ...]</code> @@ -927,48 +791,6 @@ public class NotesDatabase extends AbstractNotesDatabase { Log.v(TAG, "Deleted " + deletedNotes + " notes from account " + localAccount.getId()); } - void updateETag(long accountId, String etag) { - validateAccountId(accountId); - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(1); - values.put(key_etag, etag); - final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{String.valueOf(accountId)}); - if (updatedRows == 1) { - Log.v(TAG, "Updated etag to " + etag + " for accountId = " + accountId); - } else { - Log.e(TAG, "Updated " + updatedRows + " but expected only 1 for accountId = " + accountId + " and etag = " + etag); - } - } - - public void updateCapabilitiesETag(long accountId, String capabilitiesETag) { - validateAccountId(accountId); - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(1); - values.put(key_capabilities_etag, capabilitiesETag); - final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{String.valueOf(accountId)}); - if (updatedRows == 1) { - Log.v(TAG, "Updated etag to " + capabilitiesETag + " for accountId = " + accountId); - } else { - Log.e(TAG, "Updated " + updatedRows + " but expected only 1 for accountId = " + accountId + " and capabilitiesETag = " + capabilitiesETag); - } - } - - void updateModified(long accountId, long modified) { - validateAccountId(accountId); - if (modified < 0) { - throw new IllegalArgumentException("modified must be greater or equal 0"); - } - SQLiteDatabase db = this.getWritableDatabase(); - ContentValues values = new ContentValues(1); - values.put(key_modified, modified); - final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{String.valueOf(accountId)}); - if (updatedRows == 1) { - Log.v(TAG, "Updated modified to " + modified + " for accountId = " + accountId); - } else { - Log.e(TAG, "Updated " + updatedRows + " but expected only 1 for accountId = " + accountId + " and modified = " + modified); - } - } - /** * @param appWidgetId the id of the {@link SingleNoteWidget} * @return {@link SingleNoteWidgetData} 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 dc945d2f..24d80390 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 @@ -14,6 +14,8 @@ import it.niedermann.owncloud.notes.persistence.dao.LocalAccountDao; import it.niedermann.owncloud.notes.persistence.dao.NoteDao; import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.persistence.entity.NoteEntity; +import it.niedermann.owncloud.notes.shared.model.Capabilities; +import it.niedermann.owncloud.notes.shared.util.ColorUtil; @Database( entities = { @@ -25,13 +27,8 @@ public abstract class NotesRoomDatabase extends RoomDatabase { private static final String TAG = NotesRoomDatabase.class.getSimpleName(); private static final String NOTES_DB_NAME = "OWNCLOUD_NOTES"; - // private final NoteServerSyncHelper serverSyncHelper; private static NotesRoomDatabase instance; -// private NotesRoomDatabase(Context context) { -//// serverSyncHelper = NoteServerSyncHelper.getInstance(this); -// } - public static NotesRoomDatabase getInstance(Context context) { if (instance == null) { instance = create(context); @@ -53,20 +50,54 @@ public abstract class NotesRoomDatabase extends RoomDatabase { Log.v(TAG, NotesRoomDatabase.class.getSimpleName() + " created."); } }) + .allowMainThreadQueries() // FIXME remove .build(); } private static final Migration OLD_STUFF = new Migration(17, 18) { @Override public void migrate(SupportSQLiteDatabase database) { -// database.execSQL("ALTER TABLE `Account` ADD `color` TEXT NOT NULL DEFAULT '#0082c9'"); -// database.execSQL("ALTER TABLE `Account` ADD `textColor` TEXT NOT NULL DEFAULT '#ffffff'"); -// database.execSQL("ALTER TABLE `Account` ADD `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4'"); -// database.execSQL("ALTER TABLE `Account` ADD `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0"); + } }; public abstract NoteDao getNoteDao(); public abstract LocalAccountDao getLocalAccountDao(); + + @SuppressWarnings("UnusedReturnValue") + public long addAccount(@NonNull String url, @NonNull String username, @NonNull String accountName, @NonNull Capabilities capabilities) { + final LocalAccountEntity entity = new LocalAccountEntity(); + entity.setUrl(url); + entity.setUsername(username); + entity.setAccountName(accountName); + entity.setCapabilities(capabilities); + return getLocalAccountDao().insert(entity); + } + + public void updateBrand(long accountId, @NonNull Capabilities capabilities) throws IllegalArgumentException { + validateAccountId(accountId); + + String color; + try { + color = ColorUtil.formatColorToParsableHexString(capabilities.getColor()).substring(1); + } catch (Exception e) { + color = "0082C9"; + } + + String textColor; + try { + textColor = ColorUtil.formatColorToParsableHexString(capabilities.getTextColor()).substring(1); + } catch (Exception e) { + textColor = "FFFFFF"; + } + + getLocalAccountDao().updateBrand(accountId, color, textColor); + } + + private static void validateAccountId(long accountId) { + if (accountId < 1) { + throw new IllegalArgumentException("accountId must be greater than 0"); + } + } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/SyncWorker.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/SyncWorker.java index 4a29bd6d..810c1813 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/SyncWorker.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/SyncWorker.java @@ -20,6 +20,7 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.LocalAccount; public class SyncWorker extends Worker { @@ -38,13 +39,14 @@ public class SyncWorker extends Worker { @NonNull @Override public Result doWork() { - NotesDatabase db = NotesDatabase.getInstance(getApplicationContext()); - for (LocalAccount account : db.getAccounts()) { + NotesDatabase sqliteOpenHelperDatabase = NotesDatabase.getInstance(getApplicationContext()); + NotesRoomDatabase roomDatabase = NotesRoomDatabase.getInstance(getApplicationContext()); + for (LocalAccountEntity account : roomDatabase.getLocalAccountDao().getAccounts()) { try { SingleSignOnAccount ssoAccount = AccountImporter.getSingleSignOnAccount(getApplicationContext(), account.getAccountName()); Log.v(TAG, "Starting background synchronization for " + ssoAccount.name); - db.getNoteServerSyncHelper().addCallbackPull(ssoAccount, () -> Log.v(TAG, "Finished background synchronization for " + ssoAccount.name)); - db.getNoteServerSyncHelper().scheduleSync(ssoAccount, false); + sqliteOpenHelperDatabase.getNoteServerSyncHelper().addCallbackPull(ssoAccount, () -> Log.v(TAG, "Finished background synchronization for " + ssoAccount.name)); + sqliteOpenHelperDatabase.getNoteServerSyncHelper().scheduleSync(ssoAccount, false); } catch (NextcloudFilesAppAccountNotFoundException e) { e.printStackTrace(); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/LocalAccountDao.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/LocalAccountDao.java index cff471ff..a7c9f348 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/LocalAccountDao.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/LocalAccountDao.java @@ -1,16 +1,51 @@ package it.niedermann.owncloud.notes.persistence.dao; +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteConstraintException; +import android.database.sqlite.SQLiteDatabase; +import android.graphics.Color; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.room.Dao; +import androidx.room.Insert; import androidx.room.Query; import java.util.List; import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; +import it.niedermann.owncloud.notes.shared.model.Capabilities; +import it.niedermann.owncloud.notes.shared.model.LocalAccount; @Dao public interface LocalAccountDao { + @Insert + long insert(LocalAccountEntity localAccountEntity); + + @Query("SELECT * FROM localaccountentity WHERE id = :accountId") + LocalAccountEntity getAccount(long accountId); + + @Query("SELECT * FROM localaccountentity WHERE accountName = :accountName") + LocalAccountEntity getLocalAccountByAccountName(String accountName); @Query("SELECT * FROM localaccountentity") List<LocalAccountEntity> getAccounts(); + + @Query("SELECT COUNT(*) FROM localaccountentity") + Integer getAccountsCount(); + + @Query("UPDATE localaccountentity SET color = :color AND textColor = :textColor WHERE id = :id") + void updateBrand(long id, String color, String textColor); + + @Query("UPDATE localaccountentity SET eTag = :eTag WHERE id = :id") + void updateETag(long id, String eTag); + + @Query("UPDATE localaccountentity SET capabilitiesETag = :capabilitiesETag WHERE id = :id") + void updateCapabilitiesETag(long id, String capabilitiesETag); + + @Query("UPDATE localaccountentity SET modified = :modified WHERE id = :id") + void updateModified(long id, long modified); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/LocalAccountEntity.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/LocalAccountEntity.java index 03b7e9e7..6d28c24a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/LocalAccountEntity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/LocalAccountEntity.java @@ -1,24 +1,191 @@ package it.niedermann.owncloud.notes.persistence.entity; +import android.graphics.Color; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.room.Entity; +import androidx.room.Ignore; import androidx.room.PrimaryKey; -import it.niedermann.owncloud.notes.util.DatabaseIndexUtil; +import org.json.JSONArray; +import org.json.JSONException; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.NoSuchElementException; + +import it.niedermann.owncloud.notes.persistence.NotesClient; +import it.niedermann.owncloud.notes.shared.model.ApiVersion; +import it.niedermann.owncloud.notes.shared.model.Capabilities; +import it.niedermann.owncloud.notes.shared.model.LocalAccount; +import it.niedermann.owncloud.notes.shared.util.ColorUtil; @Entity() public class LocalAccountEntity { @PrimaryKey public int id; + private String url; + private String username; + private String accountName; + private String eTag; + private int modified; + private String apiVersion; + private String capabilitiesETag; + private String color; + private String textColor; + + @Nullable + @Ignore + private ApiVersion preferredApiVersion; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public String getETag() { + return eTag; + } + + public void setETag(String eTag) { + this.eTag = eTag; + } + + public int getModified() { + return modified; + } + + public void setModified(int modified) { + this.modified = modified; + } + + public String getApiVersion() { + return apiVersion; + } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + setPreferredApiVersion(apiVersion); + } + + public String getCapabilitiesETag() { + return capabilitiesETag; + } + + public void setCapabilitiesETag(String capabilitiesETag) { + this.capabilitiesETag = capabilitiesETag; + } + + public void setCapabilities(@NonNull Capabilities capabilities) { + capabilitiesETag = capabilities.getETag(); + apiVersion = capabilities.getApiVersion(); + setColor(capabilities.getColor()); + setTextColor(capabilities.getTextColor()); + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + try { + this.color = ColorUtil.formatColorToParsableHexString(color).substring(1); + } catch (Exception e) { + this.color = "0082C9"; + } + } + + public String getTextColor() { + return textColor; + } + + public void setTextColor(String textColor) { + try { + this.textColor = ColorUtil.formatColorToParsableHexString(textColor).substring(1); + } catch (Exception e) { + this.textColor = "FFFFFF"; + } + } + + @Nullable + public ApiVersion getPreferredApiVersion() { + return preferredApiVersion; + } + + /** + * @param availableApiVersions <code>["0.2", "1.0", ...]</code> + */ + public void setPreferredApiVersion(@Nullable String availableApiVersions) { + // TODO move this logic to NotesClient? + try { + if (availableApiVersions == null) { + this.preferredApiVersion = null; + return; + } + JSONArray versionsArray = new JSONArray(availableApiVersions); + Collection<ApiVersion> supportedApiVersions = new HashSet<>(versionsArray.length()); + for (int i = 0; i < versionsArray.length(); i++) { + ApiVersion parsedApiVersion = ApiVersion.of(versionsArray.getString(i)); + for (ApiVersion temp : NotesClient.SUPPORTED_API_VERSIONS) { + if (temp.compareTo(parsedApiVersion) == 0) { + supportedApiVersions.add(parsedApiVersion); + break; + } + } + } + this.preferredApiVersion = Collections.max(supportedApiVersions); + } catch (JSONException | NoSuchElementException e) { + e.printStackTrace(); + this.preferredApiVersion = null; + } + } - public String url; - public String username; - public String accountName; - public String eTag; - public int modified; - public String apiVersion; - public String color; - public String textColor; - public String capabilitiesETag; + @Nullable + @Deprecated + public static LocalAccount entityToLocalAccount(@Nullable LocalAccountEntity entity) { + if(entity == null) { + return null; + } + LocalAccount localAccount = new LocalAccount(); + localAccount.setAccountName(entity.getAccountName()); + localAccount.setCapabilitiesETag(entity.getCapabilitiesETag()); + localAccount.setColor(Color.parseColor('#' + entity.getColor())); + localAccount.setTextColor(Color.parseColor('#' + entity.getTextColor())); + localAccount.setETag(entity.getETag()); + localAccount.setId(entity.getId()); + localAccount.setModified(entity.getModified()); + localAccount.setUrl(entity.getUrl()); + return localAccount; + } } // DatabaseIndexUtil.createIndex(db, table_accounts, key_url, key_username, key_account_name, key_etag, key_modified);
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/account/AccountChooserAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/account/AccountChooserAdapter.java index dd28f431..6d831be3 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/account/AccountChooserAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/account/AccountChooserAdapter.java @@ -10,16 +10,19 @@ import androidx.recyclerview.widget.RecyclerView; import java.util.List; import it.niedermann.owncloud.notes.databinding.ItemAccountChooseBinding; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.shared.model.LocalAccount; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; + public class AccountChooserAdapter extends RecyclerView.Adapter<AccountChooserViewHolder> { @NonNull - private final List<LocalAccount> localAccounts; + private final List<LocalAccountEntity> localAccounts; @NonNull private final Consumer<LocalAccount> targetAccountConsumer; - public AccountChooserAdapter(@NonNull List<LocalAccount> localAccounts, @NonNull Consumer<LocalAccount> targetAccountConsumer) { + public AccountChooserAdapter(@NonNull List<LocalAccountEntity> localAccounts, @NonNull Consumer<LocalAccount> targetAccountConsumer) { super(); this.localAccounts = localAccounts; this.targetAccountConsumer = targetAccountConsumer; @@ -33,7 +36,7 @@ public class AccountChooserAdapter extends RecyclerView.Adapter<AccountChooserVi @Override public void onBindViewHolder(@NonNull AccountChooserViewHolder holder, int position) { - holder.bind(localAccounts.get(position), targetAccountConsumer); + holder.bind(entityToLocalAccount(localAccounts.get(position)), targetAccountConsumer); } @Override diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/LocalAccount.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/LocalAccount.java index aaafd750..30e50d0d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/LocalAccount.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/LocalAccount.java @@ -15,6 +15,7 @@ import java.util.NoSuchElementException; import it.niedermann.owncloud.notes.persistence.NotesClient; +@Deprecated public class LocalAccount { private long id; 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 7584b966..bdc8abe4 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 @@ -14,12 +14,13 @@ import android.widget.RemoteViews; import java.util.NoSuchElementException; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.persistence.NotesRoomDatabase; +import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity; import it.niedermann.owncloud.notes.preferences.DarkModeSetting; import it.niedermann.owncloud.notes.edit.EditNoteActivity; import it.niedermann.owncloud.notes.main.MainActivity; import it.niedermann.owncloud.notes.branding.BrandingUtil; import it.niedermann.owncloud.notes.shared.model.Category; -import it.niedermann.owncloud.notes.shared.model.LocalAccount; import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.NotesApplication; @@ -36,19 +37,20 @@ public class NoteListWidget extends AppWidgetProvider { public static final int PENDING_INTENT_OPEN_APP_RQ = 2; static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) { - final NotesDatabase db = NotesDatabase.getInstance(context); + final NotesDatabase sqliteOpenHelperDatabase = NotesDatabase.getInstance(context); + final NotesRoomDatabase roomDatabase = NotesRoomDatabase.getInstance(context); RemoteViews views; DarkModeSetting darkTheme; for (int appWidgetId : appWidgetIds) { try { - final NoteListsWidgetData data = db.getNoteListWidgetData(appWidgetId); - final LocalAccount localAccount = db.getAccount(data.getAccountId()); + final NoteListsWidgetData data = sqliteOpenHelperDatabase.getNoteListWidgetData(appWidgetId); + final LocalAccountEntity localAccountEntity = roomDatabase.getLocalAccountDao().getAccount(data.getAccountId()); String category = null; if (data.getCategoryId() != null) { - category = db.getCategoryTitleById(data.getAccountId(), data.getCategoryId()); + category = sqliteOpenHelperDatabase.getCategoryTitleById(data.getAccountId(), data.getCategoryId()); } darkTheme = DarkModeSetting.fromModeID(data.getThemeMode()); @@ -89,10 +91,10 @@ public class NoteListWidget extends AppWidgetProvider { views.setEmptyView(R.id.note_list_widget_lv_dark, R.id.widget_note_list_placeholder_tv_dark); awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.note_list_widget_lv_dark); if (BrandingUtil.isBrandingEnabled(context)) { - views.setInt(R.id.widget_note_header_dark, "setBackgroundColor", localAccount.getColor()); - views.setInt(R.id.widget_note_header_icon_dark, "setColorFilter", localAccount.getTextColor()); - views.setInt(R.id.widget_note_list_create_icon_dark, "setColorFilter", localAccount.getTextColor()); - views.setTextColor(R.id.widget_note_list_title_tv_dark, localAccount.getTextColor()); + views.setInt(R.id.widget_note_header_dark, "setBackgroundColor", Color.parseColor(localAccountEntity.getColor())); + views.setInt(R.id.widget_note_header_icon_dark, "setColorFilter", Color.parseColor(localAccountEntity.getTextColor())); + views.setInt(R.id.widget_note_list_create_icon_dark, "setColorFilter", Color.parseColor(localAccountEntity.getTextColor())); + views.setTextColor(R.id.widget_note_list_title_tv_dark, Color.parseColor(localAccountEntity.getTextColor())); } else { views.setInt(R.id.widget_note_header_dark, "setBackgroundColor", context.getResources().getColor(R.color.defaultBrand)); views.setInt(R.id.widget_note_header_icon_dark, "setColorFilter", Color.WHITE); @@ -110,10 +112,10 @@ public class NoteListWidget extends AppWidgetProvider { views.setEmptyView(R.id.note_list_widget_lv, R.id.widget_note_list_placeholder_tv); awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.note_list_widget_lv); if (BrandingUtil.isBrandingEnabled(context)) { - views.setInt(R.id.widget_note_header, "setBackgroundColor", localAccount.getColor()); - views.setInt(R.id.widget_note_header_icon, "setColorFilter", localAccount.getTextColor()); - views.setInt(R.id.widget_note_list_create_icon, "setColorFilter", localAccount.getTextColor()); - views.setTextColor(R.id.widget_note_list_title_tv, localAccount.getTextColor()); + views.setInt(R.id.widget_note_header, "setBackgroundColor", Color.parseColor(localAccountEntity.getColor())); + views.setInt(R.id.widget_note_header_icon, "setColorFilter", Color.parseColor(localAccountEntity.getTextColor())); + views.setInt(R.id.widget_note_list_create_icon, "setColorFilter", Color.parseColor(localAccountEntity.getTextColor())); + views.setTextColor(R.id.widget_note_list_title_tv, Color.parseColor(localAccountEntity.getTextColor())); } else { views.setInt(R.id.widget_note_header, "setBackgroundColor", context.getResources().getColor(R.color.defaultBrand)); views.setInt(R.id.widget_note_header_icon, "setColorFilter", Color.WHITE); 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 e927c3b1..6256f578 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 @@ -23,12 +23,15 @@ import java.util.Map; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.LockedActivity; import it.niedermann.owncloud.notes.main.MainActivity; +import it.niedermann.owncloud.notes.persistence.NotesRoomDatabase; import it.niedermann.owncloud.notes.shared.model.LocalAccount; import it.niedermann.owncloud.notes.main.NavigationAdapter; import it.niedermann.owncloud.notes.main.NavigationAdapter.CategoryNavigationItem; import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.NotesApplication; +import static it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity.entityToLocalAccount; + public class NoteListWidgetConfigurationActivity extends LockedActivity { private static final String TAG = Activity.class.getSimpleName(); @@ -40,7 +43,8 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { private NavigationAdapter adapterCategories; private NavigationAdapter.NavigationItem itemRecent; private NavigationAdapter.NavigationItem itemFavorites; - private NotesDatabase db = null; + private NotesDatabase sqliteOpenHelperDatabase = null; + private NotesRoomDatabase roomDatabase = null; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -48,9 +52,10 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { setResult(RESULT_CANCELED); setContentView(R.layout.activity_note_list_configuration); - db = NotesDatabase.getInstance(this); + sqliteOpenHelperDatabase = NotesDatabase.getInstance(this); + roomDatabase = NotesRoomDatabase.getInstance(this); try { - this.localAccount = db.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(this).name); + this.localAccount = entityToLocalAccount(roomDatabase.getLocalAccountDao().getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(this).name)); } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { e.printStackTrace(); Toast.makeText(this, R.string.widget_not_logged_in, Toast.LENGTH_LONG).show(); @@ -104,7 +109,7 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { data.setAccountId(localAccount.getId()); data.setThemeMode(NotesApplication.getAppTheme(getApplicationContext()).getModeId()); - db.createOrUpdateNoteListWidgetData(data); + sqliteOpenHelperDatabase.createOrUpdateNoteListWidgetData(data); Intent updateIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, getApplicationContext(), NoteListWidget.class); @@ -143,7 +148,7 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { return new ArrayList<>(); } NavigationAdapter.NavigationItem itemUncategorized; - List<CategoryNavigationItem> categories = db.getCategories(localAccount.getId()); + List<CategoryNavigationItem> categories = sqliteOpenHelperDatabase.getCategories(localAccount.getId()); if (!categories.isEmpty() && categories.get(0).label.isEmpty()) { itemUncategorized = categories.get(0); @@ -151,7 +156,7 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { itemUncategorized.icon = NavigationAdapter.ICON_NOFOLDER; } - Map<String, Integer> favorites = db.getFavoritesCount(localAccount.getId()); + Map<String, Integer> favorites = sqliteOpenHelperDatabase.getFavoritesCount(localAccount.getId()); //noinspection ConstantConditions int numFavorites = favorites.containsKey("1") ? favorites.get("1") : 0; //noinspection ConstantConditions 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 ef3bbbe6..25d4f408 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 @@ -52,7 +52,7 @@ public class SingleNoteWidgetConfigurationActivity extends MainActivity { int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); try { - db.createOrUpdateSingleNoteWidgetData( + sqliteOpenHelperDatabase.createOrUpdateSingleNoteWidgetData( new SingleNoteWidgetData( appWidgetId, note.getAccountId(), |