Search in sources :

Example 1 with Note

use of it.niedermann.owncloud.notes.persistence.entity.Note in project nextcloud-notes by stefan-niedermann.

the class MainActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);
    categoryViewModel = new ViewModelProvider(this).get(CategoryViewModel.class);
    CapabilitiesWorker.update(this);
    binding = DrawerLayoutBinding.inflate(getLayoutInflater());
    activityBinding = ActivityNotesListViewBinding.bind(binding.activityNotesListView.getRoot());
    setContentView(binding.getRoot());
    this.coordinatorLayout = binding.activityNotesListView.activityNotesListView;
    this.swipeRefreshLayout = binding.activityNotesListView.swiperefreshlayout;
    this.fabCreate = binding.activityNotesListView.fabCreate;
    this.listView = binding.activityNotesListView.recyclerView;
    gridView = isGridViewEnabled();
    if (!gridView || isDarkThemeActive(this)) {
        activityBinding.activityNotesListView.setBackgroundColor(ContextCompat.getColor(this, R.color.primary));
    }
    setupToolbars();
    setupNavigationList();
    setupNotesList();
    mainViewModel.getAccountsCount().observe(this, (count) -> {
        if (count == 0) {
            startActivityForResult(new Intent(this, ImportAccountActivity.class), ImportAccountActivity.REQUEST_CODE_IMPORT_ACCOUNT);
        } else {
            executor.submit(() -> {
                try {
                    final var account = mainViewModel.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()).name);
                    runOnUiThread(() -> mainViewModel.postCurrentAccount(account));
                } catch (NextcloudFilesAppAccountNotFoundException e) {
                    // Verbose log output for https://github.com/stefan-niedermann/nextcloud-notes/issues/1256
                    runOnUiThread(() -> new AlertDialog.Builder(this).setTitle(NextcloudFilesAppAccountNotFoundException.class.getSimpleName()).setMessage(R.string.backup).setPositiveButton(R.string.simple_backup, (a, b) -> executor.submit(() -> {
                        final var modifiedNotes = new LinkedList<Note>();
                        for (final var account : mainViewModel.getAccounts()) {
                            modifiedNotes.addAll(mainViewModel.getLocalModifiedNotes(account.getId()));
                        }
                        if (modifiedNotes.size() == 1) {
                            final var note = modifiedNotes.get(0);
                            ShareUtil.openShareDialog(this, note.getTitle(), note.getContent());
                        } else {
                            ShareUtil.openShareDialog(this, getResources().getQuantityString(R.plurals.share_multiple, modifiedNotes.size(), modifiedNotes.size()), mainViewModel.collectNoteContents(modifiedNotes.stream().map(Note::getId).collect(Collectors.toList())));
                        }
                    })).setNegativeButton(R.string.simple_error, (a, b) -> {
                        final var ssoPreferences = AccountImporter.getSharedPreferences(getApplicationContext());
                        final var ssoPreferencesString = new StringBuilder().append("Current SSO account: ").append(ssoPreferences.getString("PREF_CURRENT_ACCOUNT_STRING", null)).append("\n").append("\n").append("SSO SharedPreferences: ").append("\n");
                        for (final var entry : ssoPreferences.getAll().entrySet()) {
                            ssoPreferencesString.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
                        }
                        ssoPreferencesString.append("\n").append("Available accounts in DB: ").append(TextUtils.join(", ", mainViewModel.getAccounts().stream().map(Account::getAccountName).collect(Collectors.toList())));
                        runOnUiThread(() -> ExceptionDialogFragment.newInstance(new RuntimeException(e.getMessage(), new RuntimeException(ssoPreferencesString.toString(), e))).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
                    }).show());
                } catch (NoCurrentAccountSelectedException e) {
                    runOnUiThread(() -> ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
                }
            });
        }
    });
    mainViewModel.hasMultipleAccountsConfigured().observe(this, hasMultipleAccountsConfigured -> canMoveNoteToAnotherAccounts = hasMultipleAccountsConfigured);
    mainViewModel.getSyncStatus().observe(this, syncStatus -> swipeRefreshLayout.setRefreshing(syncStatus));
    mainViewModel.getSyncErrors().observe(this, exceptions -> {
        if (mainViewModel.containsNonInfrastructureRelatedItems(exceptions)) {
            BrandedSnackbar.make(coordinatorLayout, R.string.error_synchronization, Snackbar.LENGTH_LONG).setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(exceptions).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName())).show();
        }
    });
    mainViewModel.getSelectedCategory().observe(this, (selectedCategory) -> {
        binding.activityNotesListView.emptyContentView.getRoot().setVisibility(GONE);
        adapter.setShowCategory(selectedCategory.getType() == RECENT || selectedCategory.getType() == FAVORITES);
        fabCreate.show();
        switch(selectedCategory.getType()) {
            case RECENT:
                {
                    activityBinding.searchText.setText(getString(R.string.search_in_all));
                    break;
                }
            case FAVORITES:
                {
                    activityBinding.searchText.setText(getString(R.string.search_in_category, getString(R.string.label_favorites)));
                    break;
                }
            case UNCATEGORIZED:
                {
                    activityBinding.searchText.setText(getString(R.string.search_in_category, getString(R.string.action_uncategorized)));
                    break;
                }
            case DEFAULT_CATEGORY:
            default:
                {
                    final String category = selectedCategory.getCategory();
                    if (category == null) {
                        throw new IllegalStateException(NavigationCategory.class.getSimpleName() + " type is " + DEFAULT_CATEGORY + ", but category is null.");
                    }
                    activityBinding.searchText.setText(getString(R.string.search_in_category, NoteUtil.extendCategory(category)));
                    break;
                }
        }
        fabCreate.setOnClickListener((View view) -> {
            final var createIntent = new Intent(getApplicationContext(), EditNoteActivity.class);
            createIntent.putExtra(EditNoteActivity.PARAM_CATEGORY, selectedCategory);
            if (activityBinding.searchView.getQuery().length() > 0) {
                createIntent.putExtra(EditNoteActivity.PARAM_CONTENT, activityBinding.searchView.getQuery().toString());
                invalidateOptionsMenu();
            }
            startActivityForResult(createIntent, REQUEST_CODE_CREATE_NOTE);
        });
    });
    mainViewModel.getNotesListLiveData().observe(this, notes -> {
        // https://stackoverflow.com/a/37342327
        itemTouchHelper.attachToRecyclerView(null);
        itemTouchHelper.attachToRecyclerView(listView);
        adapter.setItemList(notes);
        binding.activityNotesListView.progressCircular.setVisibility(GONE);
        binding.activityNotesListView.emptyContentView.getRoot().setVisibility(notes.size() > 0 ? GONE : VISIBLE);
        // Remove deleted notes from the selection
        if (tracker.hasSelection()) {
            final var deletedNotes = new LinkedList<Long>();
            for (final var id : tracker.getSelection()) {
                if (notes.stream().filter(item -> !item.isSection()).map(item -> (Note) item).noneMatch(item -> item.getId() == id)) {
                    deletedNotes.add(id);
                }
            }
            for (final var id : deletedNotes) {
                tracker.deselect(id);
            }
        }
    });
    mainViewModel.getSearchTerm().observe(this, adapter::setHighlightSearchQuery);
    mainViewModel.getCategorySortingMethodOfSelectedCategory().observe(this, methodOfCategory -> {
        updateSortMethodIcon(methodOfCategory.second);
        activityBinding.sortingMethod.setOnClickListener((v) -> {
            if (methodOfCategory.first != null) {
                var newMethod = methodOfCategory.second;
                if (newMethod == CategorySortingMethod.SORT_LEXICOGRAPHICAL_ASC) {
                    newMethod = CategorySortingMethod.SORT_MODIFIED_DESC;
                } else {
                    newMethod = CategorySortingMethod.SORT_LEXICOGRAPHICAL_ASC;
                }
                final var modifyLiveData = mainViewModel.modifyCategoryOrder(methodOfCategory.first, newMethod);
                modifyLiveData.observe(this, (next) -> modifyLiveData.removeObservers(this));
            }
        });
    });
    mainViewModel.getNavigationCategories().observe(this, navigationItems -> this.adapterCategories.setItems(navigationItems));
    mainViewModel.getCurrentAccount().observe(this, (nextAccount) -> {
        fabCreate.hide();
        Glide.with(this).load(nextAccount.getUrl() + "/index.php/avatar/" + Uri.encode(nextAccount.getUserName()) + "/64").placeholder(R.drawable.ic_account_circle_grey_24dp).error(R.drawable.ic_account_circle_grey_24dp).apply(RequestOptions.circleCropTransform()).into(activityBinding.launchAccountSwitcher);
        mainViewModel.synchronizeNotes(nextAccount, new IResponseCallback<>() {

            @Override
            public void onSuccess(Void v) {
                Log.d(TAG, "Successfully synchronized notes for " + nextAccount.getAccountName());
            }

            @Override
            public void onError(@NonNull Throwable t) {
                runOnUiThread(() -> {
                    if (t instanceof IntendedOfflineException) {
                        Log.i(TAG, "Capabilities and notes not updated because " + nextAccount.getAccountName() + " is offline by intention.");
                    } else if (t instanceof NetworkErrorException) {
                        BrandedSnackbar.make(coordinatorLayout, getString(R.string.error_sync, getString(R.string.error_no_network)), Snackbar.LENGTH_LONG).show();
                    } else {
                        BrandedSnackbar.make(coordinatorLayout, R.string.error_synchronization, Snackbar.LENGTH_LONG).setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName())).show();
                    }
                });
            }
        });
        fabCreate.show();
        activityBinding.launchAccountSwitcher.setOnClickListener((v) -> AccountSwitcherDialog.newInstance(nextAccount.getId()).show(getSupportFragmentManager(), AccountSwitcherDialog.class.getSimpleName()));
        if (menuAdapter == null) {
            menuAdapter = new MenuAdapter(getApplicationContext(), nextAccount, REQUEST_CODE_SERVER_SETTINGS, (menuItem) -> {
                @Nullable Integer resultCode = menuItem.getResultCode();
                if (resultCode == null) {
                    startActivity(menuItem.getIntent());
                } else {
                    startActivityForResult(menuItem.getIntent(), resultCode);
                }
            });
            binding.navigationMenu.setAdapter(menuAdapter);
        } else {
            menuAdapter.updateAccount(this, nextAccount);
        }
    });
}
Also used : AlertDialog(androidx.appcompat.app.AlertDialog) HttpURLConnection(java.net.HttpURLConnection) ImportAccountActivity(it.niedermann.owncloud.notes.importaccount.ImportAccountActivity) NotesApplication.isDarkThemeActive(it.niedermann.owncloud.notes.NotesApplication.isDarkThemeActive) Bundle(android.os.Bundle) BrandedSnackbar(it.niedermann.owncloud.notes.branding.BrandedSnackbar) NonNull(androidx.annotation.NonNull) NoteClickListener(it.niedermann.owncloud.notes.shared.model.NoteClickListener) Uri(android.net.Uri) NotesColorUtil.contrastRatioIsSufficient(it.niedermann.owncloud.notes.shared.util.NotesColorUtil.contrastRatioIsSufficient) AccountPickerListener(it.niedermann.owncloud.notes.accountpicker.AccountPickerListener) SDK_INT(android.os.Build.VERSION.SDK_INT) ItemSelectionTracker(it.niedermann.owncloud.notes.main.items.selection.ItemSelectionTracker) GridItemDecoration(it.niedermann.owncloud.notes.main.items.grid.GridItemDecoration) UNCATEGORIZED(it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.UNCATEGORIZED) IntendedOfflineException(it.niedermann.owncloud.notes.exception.IntendedOfflineException) ApiProvider(it.niedermann.owncloud.notes.persistence.ApiProvider) ActionBarDrawerToggle(androidx.appcompat.app.ActionBarDrawerToggle) ActivityNotesListViewBinding(it.niedermann.owncloud.notes.databinding.ActivityNotesListViewBinding) FloatingActionButton(com.google.android.material.floatingactionbutton.FloatingActionButton) ItemAdapter(it.niedermann.owncloud.notes.main.items.ItemAdapter) VISIBLE(android.view.View.VISIBLE) View(android.view.View) CategoryDialogFragment(it.niedermann.owncloud.notes.edit.category.CategoryDialogFragment) RecyclerView(androidx.recyclerview.widget.RecyclerView) ContextCompat(androidx.core.content.ContextCompat) TokenMismatchException(com.nextcloud.android.sso.exceptions.TokenMismatchException) Log(android.util.Log) AccountSwitcherDialog(it.niedermann.owncloud.notes.accountswitcher.AccountSwitcherDialog) NavigationAdapter(it.niedermann.owncloud.notes.main.navigation.NavigationAdapter) IResponseCallback(it.niedermann.owncloud.notes.shared.model.IResponseCallback) CoordinatorLayout(androidx.coordinatorlayout.widget.CoordinatorLayout) O(android.os.Build.VERSION_CODES.O) CategoryViewModel(it.niedermann.owncloud.notes.edit.category.CategoryViewModel) R(it.niedermann.owncloud.notes.R) SearchView(androidx.appcompat.widget.SearchView) PorterDuff(android.graphics.PorterDuff) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) NetworkErrorException(android.accounts.NetworkErrorException) AccountImporter(com.nextcloud.android.sso.AccountImporter) Nullable(androidx.annotation.Nullable) UnknownErrorException(com.nextcloud.android.sso.exceptions.UnknownErrorException) SingleAccountHelper(com.nextcloud.android.sso.helper.SingleAccountHelper) GONE(android.view.View.GONE) RECENT(it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.RECENT) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) SearchManager(android.app.SearchManager) Snackbar(com.google.android.material.snackbar.Snackbar) StaggeredGridLayoutManager(androidx.recyclerview.widget.StaggeredGridLayoutManager) Account(it.niedermann.owncloud.notes.persistence.entity.Account) Note(it.niedermann.owncloud.notes.persistence.entity.Note) AlertDialog(androidx.appcompat.app.AlertDialog) LockedActivity(it.niedermann.owncloud.notes.LockedActivity) CategorySortingMethod(it.niedermann.owncloud.notes.shared.model.CategorySortingMethod) NotesApplication.isGridViewEnabled(it.niedermann.owncloud.notes.NotesApplication.isGridViewEnabled) NavigationClickListener(it.niedermann.owncloud.notes.main.navigation.NavigationClickListener) Intent(android.content.Intent) CapabilitiesWorker(it.niedermann.owncloud.notes.persistence.CapabilitiesWorker) DEFAULT_CATEGORY(it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.DEFAULT_CATEGORY) DrawableCompat(androidx.core.graphics.drawable.DrawableCompat) NextcloudFilesAppAccountNotFoundException(com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException) BrandingUtil.getSecondaryForegroundColorDependingOnTheme(it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme) NavigationCategory(it.niedermann.owncloud.notes.shared.model.NavigationCategory) CustomAppGlideModule(it.niedermann.owncloud.notes.shared.util.CustomAppGlideModule) NoteUtil(it.niedermann.owncloud.notes.shared.util.NoteUtil) MenuAdapter(it.niedermann.owncloud.notes.main.menu.MenuAdapter) LinkedList(java.util.LinkedList) ExecutorService(java.util.concurrent.ExecutorService) RequestOptions(com.bumptech.glide.request.RequestOptions) ViewModelProvider(androidx.lifecycle.ViewModelProvider) ActivityCompat(androidx.core.app.ActivityCompat) SwipeRefreshLayout(androidx.swiperefreshlayout.widget.SwipeRefreshLayout) FAVORITES(it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType.FAVORITES) DrawerLayoutBinding(it.niedermann.owncloud.notes.databinding.DrawerLayoutBinding) NotesListViewItemTouchHelper(it.niedermann.owncloud.notes.main.items.list.NotesListViewItemTouchHelper) GravityCompat(androidx.core.view.GravityCompat) AccountImportCancelledException(com.nextcloud.android.sso.exceptions.AccountImportCancelledException) NextcloudHttpRequestFailedException(com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException) CapabilitiesClient(it.niedermann.owncloud.notes.persistence.CapabilitiesClient) NavigationItem(it.niedermann.owncloud.notes.main.navigation.NavigationItem) TextUtils(android.text.TextUtils) AccountSwitcherListener(it.niedermann.owncloud.notes.accountswitcher.AccountSwitcherListener) ShareUtil(it.niedermann.owncloud.notes.shared.util.ShareUtil) ActionMode(androidx.appcompat.view.ActionMode) AnimatorInflater(android.animation.AnimatorInflater) Color(android.graphics.Color) ExceptionDialogFragment(it.niedermann.owncloud.notes.exception.ExceptionDialogFragment) SelectionTracker(androidx.recyclerview.selection.SelectionTracker) NoCurrentAccountSelectedException(com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException) Observer(androidx.lifecycle.Observer) Glide(com.bumptech.glide.Glide) EditNoteActivity(it.niedermann.owncloud.notes.edit.EditNoteActivity) SectionItemDecoration(it.niedermann.owncloud.notes.main.items.section.SectionItemDecoration) SSOUtil.askForNewAccount(it.niedermann.owncloud.notes.shared.util.SSOUtil.askForNewAccount) Account(it.niedermann.owncloud.notes.persistence.entity.Account) SSOUtil.askForNewAccount(it.niedermann.owncloud.notes.shared.util.SSOUtil.askForNewAccount) NavigationCategory(it.niedermann.owncloud.notes.shared.model.NavigationCategory) ViewModelProvider(androidx.lifecycle.ViewModelProvider) NextcloudFilesAppAccountNotFoundException(com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException) CategoryViewModel(it.niedermann.owncloud.notes.edit.category.CategoryViewModel) MenuAdapter(it.niedermann.owncloud.notes.main.menu.MenuAdapter) Intent(android.content.Intent) NoCurrentAccountSelectedException(com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException) View(android.view.View) RecyclerView(androidx.recyclerview.widget.RecyclerView) SearchView(androidx.appcompat.widget.SearchView) ImportAccountActivity(it.niedermann.owncloud.notes.importaccount.ImportAccountActivity) LinkedList(java.util.LinkedList) NetworkErrorException(android.accounts.NetworkErrorException) ExceptionDialogFragment(it.niedermann.owncloud.notes.exception.ExceptionDialogFragment) IntendedOfflineException(it.niedermann.owncloud.notes.exception.IntendedOfflineException) Note(it.niedermann.owncloud.notes.persistence.entity.Note)

Example 2 with Note

use of it.niedermann.owncloud.notes.persistence.entity.Note in project nextcloud-notes by stefan-niedermann.

the class NotesServerSyncTask method pushLocalChanges.

/**
 * Push local changes: for each locally created/edited/deleted Note, use NotesClient in order to push the changed to the server.
 */
private boolean pushLocalChanges() {
    Log.d(TAG, "pushLocalChanges()");
    boolean success = true;
    final var notes = repo.getLocalModifiedNotes(localAccount.getId());
    for (Note note : notes) {
        Log.d(TAG, "   Process Local Note: " + (BuildConfig.DEBUG ? note : note.getTitle()));
        try {
            Note remoteNote;
            switch(note.getStatus()) {
                case LOCAL_EDITED:
                    Log.v(TAG, "   ...create/edit");
                    if (note.getRemoteId() != null) {
                        Log.v(TAG, "   ...Note has remoteId → try to edit");
                        final var editResponse = notesAPI.editNote(note).execute();
                        if (editResponse.isSuccessful()) {
                            remoteNote = editResponse.body();
                            if (remoteNote == null) {
                                Log.e(TAG, "   ...Tried to edit \"" + note.getTitle() + "\" (#" + note.getId() + ") but the server response was null.");
                                throw new Exception("Server returned null after editing \"" + note.getTitle() + "\" (#" + note.getId() + ")");
                            }
                        } else if (editResponse.code() == HTTP_NOT_FOUND) {
                            Log.v(TAG, "   ...Note does no longer exist on server → recreate");
                            final var createResponse = notesAPI.createNote(note).execute();
                            if (createResponse.isSuccessful()) {
                                remoteNote = createResponse.body();
                                if (remoteNote == null) {
                                    Log.e(TAG, "   ...Tried to recreate \"" + note.getTitle() + "\" (#" + note.getId() + ") but the server response was null.");
                                    throw new Exception("Server returned null after recreating \"" + note.getTitle() + "\" (#" + note.getId() + ")");
                                }
                            } else {
                                throw new Exception(createResponse.message());
                            }
                        } else {
                            throw new Exception(editResponse.message());
                        }
                    } else {
                        Log.v(TAG, "   ...Note does not have a remoteId yet → create");
                        final var createResponse = notesAPI.createNote(note).execute();
                        if (createResponse.isSuccessful()) {
                            remoteNote = createResponse.body();
                            if (remoteNote == null) {
                                Log.e(TAG, "   ...Tried to create \"" + note.getTitle() + "\" (#" + note.getId() + ") but the server response was null.");
                                throw new Exception("Server returned null after creating \"" + note.getTitle() + "\" (#" + note.getId() + ")");
                            }
                            repo.updateRemoteId(note.getId(), remoteNote.getRemoteId());
                        } else {
                            throw new Exception(createResponse.message());
                        }
                    }
                    // Please note, that db.updateNote() realized an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
                    repo.updateIfNotModifiedLocallyDuringSync(note.getId(), remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()), note.getContent(), note.getCategory(), note.getFavorite());
                    break;
                case LOCAL_DELETED:
                    if (note.getRemoteId() == null) {
                        Log.v(TAG, "   ...delete (only local, since it has never been synchronized)");
                    } else {
                        Log.v(TAG, "   ...delete (from server and local)");
                        final var deleteResponse = notesAPI.deleteNote(note.getRemoteId()).execute();
                        if (!deleteResponse.isSuccessful()) {
                            if (deleteResponse.code() == HTTP_NOT_FOUND) {
                                Log.v(TAG, "   ...delete (note has already been deleted remotely)");
                            } else {
                                throw new Exception(deleteResponse.message());
                            }
                        }
                    }
                    // Please note, that db.deleteNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
                    repo.deleteByNoteId(note.getId(), LOCAL_DELETED);
                    break;
                default:
                    throw new IllegalStateException("Unknown State of Note " + note + ": " + note.getStatus());
            }
        } catch (NextcloudHttpRequestFailedException e) {
            if (e.getStatusCode() == HTTP_NOT_MODIFIED) {
                Log.d(TAG, "Server returned HTTP Status Code 304 - Not Modified");
            } else {
                exceptions.add(e);
                success = false;
            }
        } catch (Exception e) {
            if (e instanceof TokenMismatchException) {
                apiProvider.invalidateAPICache(ssoAccount);
            }
            exceptions.add(e);
            success = false;
        }
    }
    return success;
}
Also used : TokenMismatchException(com.nextcloud.android.sso.exceptions.TokenMismatchException) Note(it.niedermann.owncloud.notes.persistence.entity.Note) NextcloudHttpRequestFailedException(com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException) NextcloudApiNotRespondingException(com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException) NextcloudFilesAppAccountNotFoundException(com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException) TokenMismatchException(com.nextcloud.android.sso.exceptions.TokenMismatchException) NextcloudHttpRequestFailedException(com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException)

Example 3 with Note

use of it.niedermann.owncloud.notes.persistence.entity.Note in project nextcloud-notes by stefan-niedermann.

the class NoteListWidgetFactory method getViewAt.

@Override
public RemoteViews getViewAt(int position) {
    final RemoteViews note_content;
    if (position == 0) {
        final Account localAccount = repo.getAccountById(data.getAccountId());
        final Intent openIntent = new Intent(Intent.ACTION_MAIN).setComponent(new ComponentName(context.getPackageName(), MainActivity.class.getName()));
        final Intent createIntent = new Intent(context, EditNoteActivity.class);
        final Bundle extras = new Bundle();
        extras.putSerializable(PARAM_CATEGORY, data.getMode() == MODE_DISPLAY_STARRED ? new NavigationCategory(ENavigationCategoryType.FAVORITES) : new NavigationCategory(localAccount.getId(), data.getCategory()));
        extras.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, data.getAccountId());
        createIntent.putExtras(extras);
        createIntent.setData(Uri.parse(createIntent.toUri(Intent.URI_INTENT_SCHEME)));
        note_content = new RemoteViews(context.getPackageName(), R.layout.widget_entry_add);
        note_content.setOnClickFillInIntent(R.id.widget_entry_content_tv, openIntent);
        note_content.setOnClickFillInIntent(R.id.widget_entry_fav_icon, createIntent);
        note_content.setTextViewText(R.id.widget_entry_content_tv, getCategoryTitle(context, data.getMode(), data.getCategory()));
        note_content.setImageViewResource(R.id.widget_entry_fav_icon, R.drawable.ic_add_blue_24dp);
        note_content.setInt(R.id.widget_entry_fav_icon, "setColorFilter", NotesColorUtil.contrastRatioIsSufficient(ContextCompat.getColor(context, R.color.widget_background), localAccount.getColor()) ? localAccount.getColor() : ContextCompat.getColor(context, R.color.widget_foreground));
    } else {
        position--;
        if (position > dbNotes.size() - 1 || dbNotes.get(position) == null) {
            Log.e(TAG, "Could not find position \"" + position + "\" in dbNotes list.");
            return null;
        }
        final Note note = dbNotes.get(position);
        final Intent fillInIntent = new Intent(context, EditNoteActivity.class);
        final Bundle extras = new Bundle();
        extras.putLong(EditNoteActivity.PARAM_NOTE_ID, note.getId());
        extras.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, note.getAccountId());
        fillInIntent.putExtras(extras);
        fillInIntent.setData(Uri.parse(fillInIntent.toUri(Intent.URI_INTENT_SCHEME)));
        note_content = new RemoteViews(context.getPackageName(), R.layout.widget_entry);
        note_content.setOnClickFillInIntent(R.id.widget_note_list_entry, fillInIntent);
        note_content.setTextViewText(R.id.widget_entry_content_tv, note.getTitle());
        note_content.setImageViewResource(R.id.widget_entry_fav_icon, note.getFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp);
    }
    return note_content;
}
Also used : Account(it.niedermann.owncloud.notes.persistence.entity.Account) RemoteViews(android.widget.RemoteViews) Bundle(android.os.Bundle) NavigationCategory(it.niedermann.owncloud.notes.shared.model.NavigationCategory) Note(it.niedermann.owncloud.notes.persistence.entity.Note) Intent(android.content.Intent) ComponentName(android.content.ComponentName)

Example 4 with Note

use of it.niedermann.owncloud.notes.persistence.entity.Note in project nextcloud-notes by stefan-niedermann.

the class NotesDaoTest method getRemoteIds.

@Test
public void getRemoteIds() {
    final var secondAccount = setupSecondAccount();
    db.getNoteDao().addNote(new Note(1, 4711L, Calendar.getInstance(), "T", "C", "", false, "1", VOID, account.getId(), "", 0));
    db.getNoteDao().addNote(new Note(2, 1234L, Calendar.getInstance(), "T", "C", "", false, "1", LOCAL_EDITED, account.getId(), "", 0));
    db.getNoteDao().addNote(new Note(3, 1234L, Calendar.getInstance(), "T", "C", "", false, "1", LOCAL_EDITED, secondAccount.getId(), "", 0));
    db.getNoteDao().addNote(new Note(4, 6969L, Calendar.getInstance(), "T", "C", "", false, "1", LOCAL_DELETED, account.getId(), "", 0));
    final List<Long> remoteIdsOfAccount = db.getNoteDao().getRemoteIds(account.getId());
    assertTrue(remoteIdsOfAccount.stream().anyMatch(id -> 4711 == id));
    assertTrue(remoteIdsOfAccount.stream().anyMatch(id -> 1234 == id));
    assertEquals("Remote IDs can only occur a single time, like in a set.", 1, remoteIdsOfAccount.stream().filter(id -> 1234 == id).count());
    assertFalse("Remote IDs from notes of other accounts must not be returned.", remoteIdsOfAccount.stream().anyMatch(id -> 6969 == id));
}
Also used : Note(it.niedermann.owncloud.notes.persistence.entity.Note) DBStatus(it.niedermann.owncloud.notes.shared.model.DBStatus) NonNull(androidx.annotation.NonNull) RunWith(org.junit.runner.RunWith) LOCAL_EDITED(it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_EDITED) ApplicationProvider(androidx.test.core.app.ApplicationProvider) CategoryWithNotesCount(it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount) InstantTaskExecutorRule(androidx.arch.core.executor.testing.InstantTaskExecutorRule) Calendar(java.util.Calendar) After(org.junit.After) Before(org.junit.Before) LOCAL_DELETED(it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED) Capabilities(it.niedermann.owncloud.notes.shared.model.Capabilities) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Room(androidx.room.Room) VOID(it.niedermann.owncloud.notes.shared.model.DBStatus.VOID) Assert.assertNotEquals(org.junit.Assert.assertNotEquals) RobolectricTestRunner(org.robolectric.RobolectricTestRunner) List(java.util.List) Rule(org.junit.Rule) Assert.assertNull(org.junit.Assert.assertNull) Assert.assertFalse(org.junit.Assert.assertFalse) SQLiteConstraintException(android.database.sqlite.SQLiteConstraintException) Account(it.niedermann.owncloud.notes.persistence.entity.Account) Assert.assertEquals(org.junit.Assert.assertEquals) Note(it.niedermann.owncloud.notes.persistence.entity.Note) Test(org.junit.Test)

Example 5 with Note

use of it.niedermann.owncloud.notes.persistence.entity.Note in project nextcloud-notes by stefan-niedermann.

the class NotesDaoTest method updateCategory.

@Test
public void updateCategory() {
    db.getNoteDao().addNote(new Note(1, 1L, Calendar.getInstance(), "T", "C", "", false, "1", LOCAL_DELETED, account.getId(), "", 0));
    db.getNoteDao().updateCategory(1, "日记");
    assertEquals("日记", db.getNoteDao().getNoteById(1).getCategory());
}
Also used : Note(it.niedermann.owncloud.notes.persistence.entity.Note) Test(org.junit.Test)

Aggregations

Note (it.niedermann.owncloud.notes.persistence.entity.Note)21 Test (org.junit.Test)13 Account (it.niedermann.owncloud.notes.persistence.entity.Account)5 Intent (android.content.Intent)3 NonNull (androidx.annotation.NonNull)3 NextcloudFilesAppAccountNotFoundException (com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException)3 Capabilities (it.niedermann.owncloud.notes.shared.model.Capabilities)3 NavigationCategory (it.niedermann.owncloud.notes.shared.model.NavigationCategory)3 Before (org.junit.Before)3 SQLiteConstraintException (android.database.sqlite.SQLiteConstraintException)2 Bundle (android.os.Bundle)2 InstantTaskExecutorRule (androidx.arch.core.executor.testing.InstantTaskExecutorRule)2 Room (androidx.room.Room)2 ApplicationProvider (androidx.test.core.app.ApplicationProvider)2 NextcloudHttpRequestFailedException (com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException)2 TokenMismatchException (com.nextcloud.android.sso.exceptions.TokenMismatchException)2 CategoryWithNotesCount (it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount)2 DBStatus (it.niedermann.owncloud.notes.shared.model.DBStatus)2 LOCAL_DELETED (it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED)2 LOCAL_EDITED (it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_EDITED)2