Search in sources :

Example 1 with CategoryViewModel

use of it.niedermann.owncloud.notes.edit.category.CategoryViewModel 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)

Aggregations

NetworkErrorException (android.accounts.NetworkErrorException)1 AnimatorInflater (android.animation.AnimatorInflater)1 SearchManager (android.app.SearchManager)1 Intent (android.content.Intent)1 Color (android.graphics.Color)1 PorterDuff (android.graphics.PorterDuff)1 Uri (android.net.Uri)1 SDK_INT (android.os.Build.VERSION.SDK_INT)1 O (android.os.Build.VERSION_CODES.O)1 Bundle (android.os.Bundle)1 TextUtils (android.text.TextUtils)1 Log (android.util.Log)1 View (android.view.View)1 GONE (android.view.View.GONE)1 VISIBLE (android.view.View.VISIBLE)1 NonNull (androidx.annotation.NonNull)1 Nullable (androidx.annotation.Nullable)1 ActionBarDrawerToggle (androidx.appcompat.app.ActionBarDrawerToggle)1 AlertDialog (androidx.appcompat.app.AlertDialog)1 ActionMode (androidx.appcompat.view.ActionMode)1