Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 05966ead authored by stefan-niedermann's avatar stefan-niedermann
Browse files

Divide et impera

parent 13021655
Loading
Loading
Loading
Loading
+128 −0
Original line number Diff line number Diff line
package it.niedermann.owncloud.notes.android;

import android.content.Context;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import androidx.appcompat.view.ActionMode;
import androidx.appcompat.view.ActionMode.Callback;
import androidx.appcompat.widget.SearchView;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.snackbar.Snackbar;

import java.util.ArrayList;
import java.util.List;

import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity;
import it.niedermann.owncloud.notes.android.fragment.AccountChooserDialogFragment;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.ItemAdapter;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
import it.niedermann.owncloud.notes.util.ICallback;

public class MultiSelectedActionModeCallback implements Callback {

    private Context context;
    private ViewProvider viewProvider;
    private NoteSQLiteOpenHelper db;
    private ActionMode actionMode;
    private ItemAdapter adapter;
    private RecyclerView recyclerView;
    private Runnable refreshLists;
    private FragmentManager fragmentManager;
    private SearchView searchView;

    public MultiSelectedActionModeCallback(
            Context context, ViewProvider viewProvider, NoteSQLiteOpenHelper db, ActionMode actionMode, ItemAdapter adapter, RecyclerView recyclerView, Runnable refreshLists, FragmentManager fragmentManager, SearchView searchView) {
        this.context = context;
        this.viewProvider = viewProvider;
        this.db = db;
        this.actionMode = actionMode;
        this.adapter = adapter;
        this.recyclerView = recyclerView;
        this.refreshLists = refreshLists;
        this.fragmentManager = fragmentManager;
        this.searchView = searchView;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // inflate contextual menu
        mode.getMenuInflater().inflate(R.menu.menu_list_context_multiple, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    /**
     * @param mode ActionMode - used to close the Action Bar after all work is done.
     * @param item MenuItem - the item in the List that contains the Node
     * @return boolean
     */
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_delete: {
                List<DBNote> deletedNotes = new ArrayList<>();
                List<Integer> selection = adapter.getSelected();
                for (Integer i : selection) {
                    DBNote note = (DBNote) adapter.getItem(i);
                    deletedNotes.add(db.getNote(note.getAccountId(), note.getId()));
                    db.deleteNoteAndSync(note.getId());
                }
                mode.finish(); // Action picked, so close the CAB
                //after delete selection has to be cleared
                searchView.setIconified(true);
                refreshLists.run();
                String deletedSnackbarTitle = deletedNotes.size() == 1
                        ? context.getString(R.string.action_note_deleted, deletedNotes.get(0).getTitle())
                        : context.getString(R.string.bulk_notes_deleted, deletedNotes.size());
                Snackbar.make(viewProvider.getView(), deletedSnackbarTitle, Snackbar.LENGTH_LONG)
                        .setAction(R.string.action_undo, (View v) -> {
                            db.getNoteServerSyncHelper().addCallbackPush(new ICallback() {
                                @Override
                                public void onFinish() {
                                    refreshLists.run();
                                }

                                @Override
                                public void onScheduled() {

                                }
                            });
                            for (DBNote deletedNote : deletedNotes) {
                                db.addNoteAndSync(deletedNote.getAccountId(), deletedNote);
                            }
                            refreshLists.run();
                            String restoreSnackbarTitle = deletedNotes.size() == 1
                                    ? context.getString(R.string.action_note_restored, deletedNotes.get(0).getTitle())
                                    : context.getString(R.string.bulk_notes_restored, deletedNotes.size());
                            Snackbar.make(viewProvider.getView(), restoreSnackbarTitle, Snackbar.LENGTH_SHORT)
                                    .show();
                        })
                        .show();
                return true;
            }
            case R.id.menu_move: {
                AccountChooserDialogFragment.newInstance().show(fragmentManager, NotesListViewActivity.class.getCanonicalName());
                return true;
            }
        }
        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        adapter.clearSelection(recyclerView);
        actionMode = null;
        adapter.notifyDataSetChanged();
    }
}
+118 −0
Original line number Diff line number Diff line
package it.niedermann.owncloud.notes.android;

import android.content.Context;
import android.graphics.Canvas;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.snackbar.Snackbar;

import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.ItemAdapter;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
import it.niedermann.owncloud.notes.util.ICallback;

public class NotesListViewItemTouchHelper extends ItemTouchHelper {

    private static final String TAG = NotesListViewItemTouchHelper.class.getCanonicalName();

    public NotesListViewItemTouchHelper(
            Context context,
            ViewProvider viewProvider,
            NoteSQLiteOpenHelper db,
            ItemAdapter adapter,
            ICallback syncCallBack,
            Runnable refreshLists
    ) {
        super(new SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                return false;
            }

            /**
             * Disable swipe on sections
             *
             * @param recyclerView RecyclerView
             * @param viewHolder   RecyclerView.ViewHoler
             * @return 0 if section, otherwise super()
             */
            @Override
            public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
                if (viewHolder instanceof ItemAdapter.SectionViewHolder) return 0;
                return super.getSwipeDirs(recyclerView, viewHolder);
            }

            /**
             * Delete note if note is swiped to left or right
             *
             * @param viewHolder RecyclerView.ViewHoler
             * @param direction  int
             */
            @Override
            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
                switch (direction) {
                    case ItemTouchHelper.LEFT: {
                        final DBNote dbNoteWithoutContent = (DBNote) adapter.getItem(viewHolder.getAdapterPosition());
                        final DBNote dbNote = db.getNote(dbNoteWithoutContent.getAccountId(), dbNoteWithoutContent.getId());
                        db.deleteNoteAndSync(dbNote.getId());
                        adapter.remove(dbNote);
                        refreshLists.run();
                        Log.v(TAG, "Item deleted through swipe ----------------------------------------------");
                        Snackbar.make(viewProvider.getView(), context.getString(R.string.action_note_deleted, dbNote.getTitle()), Snackbar.LENGTH_LONG)
                                .setAction(R.string.action_undo, (View v) -> {
                                    db.getNoteServerSyncHelper().addCallbackPush(new ICallback() {
                                        @Override
                                        public void onFinish() {
                                            refreshLists.run();
                                        }

                                        @Override
                                        public void onScheduled() {

                                        }
                                    });
                                    db.addNoteAndSync(dbNote.getAccountId(), dbNote);
                                    refreshLists.run();
                                    Snackbar.make(viewProvider.getView(), context.getString(R.string.action_note_restored, dbNote.getTitle()), Snackbar.LENGTH_SHORT)
                                            .show();
                                })
                                .show();
                        break;
                    }
                    case ItemTouchHelper.RIGHT: {
                        final DBNote dbNote = (DBNote) adapter.getItem(viewHolder.getAdapterPosition());
                        db.toggleFavorite(dbNote, syncCallBack);
                        refreshLists.run();
                        break;
                    }
                }
            }

            @Override
            public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
                ItemAdapter.NoteViewHolder noteViewHolder = (ItemAdapter.NoteViewHolder) viewHolder;
                // show swipe icon on the side
                noteViewHolder.showSwipe(dX > 0);
                // move only swipeable part of item (not leave-behind)
                getDefaultUIUtil().onDraw(c, recyclerView, noteViewHolder.noteSwipeable, dX, dY, actionState, isCurrentlyActive);
            }

            @Override
            public float getSwipeEscapeVelocity(float defaultValue) {
                return defaultValue * 3;
            }

            @Override
            public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
                getDefaultUIUtil().clearView(((ItemAdapter.NoteViewHolder) viewHolder).noteSwipeable);
            }
        });
    }
}
Loading