Search in sources :

Example 16 with UNDO

use of com.ichi2.async.CollectionTask.TASK_TYPE.UNDO in project Anki-Android by Ramblurr.

the class DeckTask method doInBackgroundDismissNote.

private TaskData doInBackgroundDismissNote(TaskData... params) {
    Sched sched = params[0].getSched();
    Collection col = sched.getCol();
    Card card = params[0].getCard();
    Note note = card.note();
    int type = params[0].getInt();
    try {
        col.getDb().getDatabase().beginTransaction();
        try {
            switch(type) {
                case 4:
                    // collect undo information
                    col.markUndo(Collection.UNDO_BURY_CARD, new Object[] { col.getDirty(), note.cards(), card.getId() });
                    // then bury
                    sched.buryCards(new long[] { card.getId() });
                    sHadCardQueue = true;
                    break;
                case 0:
                    // collect undo information
                    col.markUndo(Collection.UNDO_BURY_NOTE, new Object[] { col.getDirty(), note.cards(), card.getId() });
                    // then bury
                    sched.buryNote(note.getId());
                    sHadCardQueue = true;
                    break;
                case 1:
                    // collect undo information
                    col.markUndo(Collection.UNDO_SUSPEND_CARD, new Object[] { card });
                    // suspend card
                    if (card.getQueue() == -1) {
                        sched.unsuspendCards(new long[] { card.getId() });
                    } else {
                        sched.suspendCards(new long[] { card.getId() });
                    }
                    sHadCardQueue = true;
                    break;
                case 2:
                    // collect undo information
                    ArrayList<Card> cards = note.cards();
                    long[] cids = new long[cards.size()];
                    for (int i = 0; i < cards.size(); i++) {
                        cids[i] = cards.get(i).getId();
                    }
                    col.markUndo(Collection.UNDO_SUSPEND_NOTE, new Object[] { cards, card.getId() });
                    // suspend note
                    sched.suspendCards(cids);
                    sHadCardQueue = true;
                    break;
                case 3:
                    // collect undo information
                    ArrayList<Card> allCs = note.cards();
                    long[] cardIds = new long[allCs.size()];
                    for (int i = 0; i < allCs.size(); i++) {
                        cardIds[i] = allCs.get(i).getId();
                    }
                    col.markUndo(Collection.UNDO_DELETE_NOTE, new Object[] { note, allCs, card.getId() });
                    // delete note
                    col.remNotes(new long[] { note.getId() });
                    sHadCardQueue = true;
                    break;
            }
            publishProgress(new TaskData(getCard(col.getSched()), 0));
            col.getDb().getDatabase().setTransactionSuccessful();
        } finally {
            col.getDb().getDatabase().endTransaction();
        }
    } catch (RuntimeException e) {
        Log.e(AnkiDroidApp.TAG, "doInBackgroundSuspendCard - RuntimeException on suspending card: " + e);
        AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundSuspendCard");
        return new TaskData(false);
    }
    return new TaskData(true);
}
Also used : Sched(com.ichi2.libanki.Sched) Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Card(com.ichi2.libanki.Card)

Example 17 with UNDO

use of com.ichi2.async.CollectionTask.TASK_TYPE.UNDO in project Anki-Android by Ramblurr.

the class DeckTask method doInBackgroundUpdateNote.

private TaskData doInBackgroundUpdateNote(TaskData[] params) {
    // Log.i(AnkiDroidApp.TAG, "doInBackgroundUpdateNote");
    // Save the note
    Sched sched = params[0].getSched();
    Collection col = sched.getCol();
    Card editCard = params[0].getCard();
    Note editNote = editCard.note();
    boolean fromReviewer = params[0].getBoolean();
    // mark undo
    col.markUndo(Collection.UNDO_EDIT_NOTE, new Object[] { col.getNote(editNote.getId()), editCard.getId(), fromReviewer });
    try {
        col.getDb().getDatabase().beginTransaction();
        try {
            // TODO: undo integration
            editNote.flush();
            // flush card too, in case, did has been changed
            editCard.flush();
            if (fromReviewer) {
                Card newCard;
                if (col.getDecks().active().contains(editCard.getDid())) {
                    newCard = editCard;
                    newCard.load();
                    // reload qa-cache
                    newCard.getQuestion(true);
                } else {
                    newCard = getCard(sched);
                }
                publishProgress(new TaskData(newCard));
            } else {
                publishProgress(new TaskData(editCard, editNote.stringTags()));
            }
            col.getDb().getDatabase().setTransactionSuccessful();
        } finally {
            col.getDb().getDatabase().endTransaction();
        }
    } catch (RuntimeException e) {
        Log.e(AnkiDroidApp.TAG, "doInBackgroundUpdateNote - RuntimeException on updating fact: " + e);
        AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundUpdateNote");
        return new TaskData(false);
    }
    return new TaskData(true);
}
Also used : Sched(com.ichi2.libanki.Sched) Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Card(com.ichi2.libanki.Card)

Example 18 with UNDO

use of com.ichi2.async.CollectionTask.TASK_TYPE.UNDO in project Anki-Android by Ramblurr.

the class Connection method doInBackgroundSync.

private Payload doInBackgroundSync(Payload data) {
    // for for doInBackgroundLoadDeckCounts if any
    DeckTask.waitToFinish();
    String hkey = (String) data.data[0];
    boolean media = (Boolean) data.data[1];
    String conflictResolution = (String) data.data[2];
    int mediaUsn = (Integer) data.data[3];
    boolean colCorruptFullSync = false;
    Collection col = AnkiDroidApp.getCol();
    if (!AnkiDroidApp.colIsOpen()) {
        if (conflictResolution != null && conflictResolution.equals("download")) {
            colCorruptFullSync = true;
        } else {
            data.success = false;
            data.result = new Object[] { "genericError" };
            return data;
        }
    }
    String path = AnkiDroidApp.getCollectionPath();
    BasicHttpSyncer server = new RemoteServer(this, hkey);
    Syncer client = new Syncer(col, server);
    // run sync and check state
    boolean noChanges = false;
    if (conflictResolution == null) {
        // Log.i(AnkiDroidApp.TAG, "Sync - starting sync");
        publishProgress(R.string.sync_prepare_syncing);
        Object[] ret = client.sync(this);
        data.message = client.getSyncMsg();
        mediaUsn = client.getmMediaUsn();
        if (ret == null) {
            data.success = false;
            data.result = new Object[] { "genericError" };
            return data;
        }
        String retCode = (String) ret[0];
        if (!retCode.equals("noChanges") && !retCode.equals("success")) {
            data.success = false;
            data.result = ret;
            // note mediaUSN for later
            data.data = new Object[] { mediaUsn };
            return data;
        }
        // save and note success state
        if (retCode.equals("noChanges")) {
            // publishProgress(R.string.sync_no_changes_message);
            noChanges = true;
        } else {
        // publishProgress(R.string.sync_database_success);
        }
    } else {
        try {
            server = new FullSyncer(col, hkey, this);
            if (conflictResolution.equals("upload")) {
                // Log.i(AnkiDroidApp.TAG, "Sync - fullsync - upload collection");
                publishProgress(R.string.sync_preparing_full_sync_message);
                Object[] ret = server.upload();
                if (ret == null) {
                    data.success = false;
                    data.result = new Object[] { "genericError" };
                    AnkiDroidApp.openCollection(path);
                    return data;
                }
                if (!((String) ret[0]).equals(BasicHttpSyncer.ANKIWEB_STATUS_OK)) {
                    data.success = false;
                    data.result = ret;
                    AnkiDroidApp.openCollection(path);
                    return data;
                }
            } else if (conflictResolution.equals("download")) {
                // Log.i(AnkiDroidApp.TAG, "Sync - fullsync - download collection");
                publishProgress(R.string.sync_downloading_message);
                Object[] ret = server.download();
                if (ret == null) {
                    data.success = false;
                    data.result = new Object[] { "genericError" };
                    AnkiDroidApp.openCollection(path);
                    return data;
                }
                if (!((String) ret[0]).equals("success")) {
                    data.success = false;
                    data.result = ret;
                    if (!colCorruptFullSync) {
                        AnkiDroidApp.openCollection(path);
                    }
                    return data;
                }
            }
            col = AnkiDroidApp.openCollection(path);
        } catch (OutOfMemoryError e) {
            AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundSync-fullSync");
            data.success = false;
            data.result = new Object[] { "OutOfMemoryError" };
            data.data = new Object[] { mediaUsn };
            return data;
        } catch (RuntimeException e) {
            AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundSync-fullSync");
            data.success = false;
            data.result = new Object[] { "IOException" };
            data.data = new Object[] { mediaUsn };
            return data;
        }
    }
    // clear undo to avoid non syncing orphans (because undo resets usn too
    if (!noChanges) {
        col.clearUndo();
    }
    // then move on to media sync
    boolean noMediaChanges = false;
    String mediaError = null;
    if (media) {
        server = new RemoteMediaServer(hkey, this);
        MediaSyncer mediaClient = new MediaSyncer(col, (RemoteMediaServer) server);
        String ret;
        try {
            ret = mediaClient.sync(mediaUsn, this);
            if (ret == null) {
                mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_error);
            } else {
                if (ret.equals("noChanges")) {
                    publishProgress(R.string.sync_media_no_changes);
                    noMediaChanges = true;
                }
                if (ret.equals("sanityFailed")) {
                    mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_sanity_failed);
                } else {
                    publishProgress(R.string.sync_media_success);
                }
            }
        } catch (RuntimeException e) {
            AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundSync-mediaSync");
            mediaError = e.getLocalizedMessage();
        }
    }
    if (noChanges && noMediaChanges) {
        data.success = false;
        data.result = new Object[] { "noChanges" };
        return data;
    } else {
        data.success = true;
        TreeSet<Object[]> decks = col.getSched().deckDueTree();
        int[] counts = new int[] { 0, 0, 0 };
        for (Object[] deck : decks) {
            if (((String[]) deck[0]).length == 1) {
                counts[0] += (Integer) deck[2];
                counts[1] += (Integer) deck[3];
                counts[2] += (Integer) deck[4];
            }
        }
        Object[] dc = col.getSched().deckCounts();
        data.result = dc[0];
        data.data = new Object[] { conflictResolution, col, dc[1], dc[2], mediaError };
        return data;
    }
}
Also used : FullSyncer(com.ichi2.libanki.sync.FullSyncer) OutOfMemoryError(java.lang.OutOfMemoryError) BasicHttpSyncer(com.ichi2.libanki.sync.BasicHttpSyncer) FullSyncer(com.ichi2.libanki.sync.FullSyncer) MediaSyncer(com.ichi2.libanki.sync.MediaSyncer) BasicHttpSyncer(com.ichi2.libanki.sync.BasicHttpSyncer) Syncer(com.ichi2.libanki.sync.Syncer) Collection(com.ichi2.libanki.Collection) MediaSyncer(com.ichi2.libanki.sync.MediaSyncer) JSONObject(org.json.JSONObject) RemoteServer(com.ichi2.libanki.sync.RemoteServer) RemoteMediaServer(com.ichi2.libanki.sync.RemoteMediaServer)

Example 19 with UNDO

use of com.ichi2.async.CollectionTask.TASK_TYPE.UNDO in project AnkiChinaAndroid by ankichinateam.

the class SelfStudyActivity method onOptionsItemSelected.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // (when another operation will be performed on the model, it will undo the latest operation)
    if (mUndoSnackbar != null && mUndoSnackbar.isShown()) {
        mUndoSnackbar.dismiss();
    }
    switch(item.getItemId()) {
        case android.R.id.home:
            endMultiSelectMode();
            return true;
        case R.id.screen:
            showScreenDialog();
            return true;
        case R.id.action_edit:
            mCardsAdapter.setMultiCheckable(!mCardsAdapter.isMultiCheckableMode());
            return true;
        case R.id.action_add_note_from_card_browser:
            {
                Intent intent = new Intent(SelfStudyActivity.this, NoteEditor.class);
                intent.putExtra(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_CARDBROWSER_ADD);
                startActivityForResultWithAnimation(intent, ADD_NOTE, ActivityTransitionAnimation.LEFT);
                return true;
            }
        case R.id.action_save_search:
            {
                String searchTerms = mSearchView.getQuery().toString();
                showDialogFragment(CardBrowserMySearchesDialog.newInstance(null, mMySearchesDialogListener, searchTerms, CardBrowserMySearchesDialog.CARD_BROWSER_MY_SEARCHES_TYPE_SAVE));
                return true;
            }
        case R.id.action_list_my_searches:
            {
                JSONObject savedFiltersObj = getCol().getConf().optJSONObject("savedFilters");
                HashMap<String, String> savedFilters = new HashMap<>();
                if (savedFiltersObj != null) {
                    Iterator<String> it = savedFiltersObj.keys();
                    while (it.hasNext()) {
                        String searchName = it.next();
                        savedFilters.put(searchName, savedFiltersObj.optString(searchName));
                    }
                }
                showDialogFragment(CardBrowserMySearchesDialog.newInstance(savedFilters, mMySearchesDialogListener, "", CardBrowserMySearchesDialog.CARD_BROWSER_MY_SEARCHES_TYPE_LIST));
                return true;
            }
        case R.id.action_sort_by_size:
            showDialogFragment(CardBrowserOrderDialog.newInstance(mOrder, mOrderAsc, mOrderDialogListener));
            return true;
        case R.id.action_show_marked:
            mSearchTerms = "tag:marked";
            mSearchView.setQuery("", false);
            mSearchView.setQueryHint(getResources().getString(R.string.card_browser_show_marked));
            searchCards();
            return true;
        case R.id.action_show_suspended:
            mSearchTerms = "is:suspended";
            mSearchView.setQuery("", false);
            mSearchView.setQueryHint(getResources().getString(R.string.card_browser_show_suspended));
            searchCards();
            return true;
        case R.id.action_flag_zero:
            flagTask(0);
            return true;
        case R.id.action_flag_one:
            flagTask(1);
            return true;
        case R.id.action_flag_two:
            flagTask(2);
            return true;
        case R.id.action_flag_three:
            flagTask(3);
            return true;
        case R.id.action_flag_four:
            flagTask(4);
            return true;
        case R.id.action_delete_card:
            if (inMultiSelectMode()) {
                CollectionTask.launchCollectionTask(DISMISS_MULTI, mDeleteNoteHandler, new TaskData(new Object[] { getSelectedCardIds(), Collection.DismissType.DELETE_NOTE_MULTI }));
                mCardsAdapter.getSelectedItemIds().clear();
            }
            return true;
        case R.id.action_mark_card:
            CollectionTask.launchCollectionTask(DISMISS_MULTI, markCardHandler(), new TaskData(new Object[] { getSelectedCardIds(), Collection.DismissType.MARK_NOTE_MULTI }));
            return true;
        case R.id.action_suspend_card:
            CollectionTask.launchCollectionTask(DISMISS_MULTI, suspendCardHandler(), new TaskData(new Object[] { getSelectedCardIds(), Collection.DismissType.SUSPEND_CARD_MULTI }));
            toggleMultiSelectMode(false);
            return true;
        case R.id.action_change_deck:
            {
                AlertDialog.Builder builderSingle = new AlertDialog.Builder(this);
                builderSingle.setTitle(getString(R.string.move_all_to_deck));
                // WARNING: changeDeck depends on this index, so any changes should be reflected there.
                final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.dropdown_deck_item);
                for (Deck deck : getValidDecksForChangeDeck()) {
                    try {
                        arrayAdapter.add(deck.getString("name"));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                builderSingle.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.dismiss());
                builderSingle.setAdapter(arrayAdapter, (dialog, which) -> changeDeck(which));
                builderSingle.show();
                return true;
            }
        case R.id.action_undo:
            if (getCol().undoAvailable()) {
                CollectionTask.launchCollectionTask(UNDO, mUndoHandler);
            }
            return true;
        case R.id.action_preview:
            {
                mStartStudyButton.performClick();
                return true;
            }
        case R.id.action_reset_cards_progress:
            {
                Timber.i("NoteEditor:: Reset progress button pressed");
                // Show confirmation dialog before resetting card progress
                ConfirmationDialog dialog = new ConfirmationDialog();
                String title = getString(R.string.reset_card_dialog_title);
                String message = getString(R.string.reset_card_dialog_message);
                dialog.setArgs(title, message);
                Runnable confirm = () -> {
                    Timber.i("CardBrowser:: ResetProgress button pressed");
                    CollectionTask.launchCollectionTask(DISMISS_MULTI, resetProgressCardHandler(), new TaskData(new Object[] { getSelectedCardIds(), Collection.DismissType.RESET_CARDS }));
                };
                dialog.setConfirm(confirm);
                showDialogFragment(dialog);
                return true;
            }
        case R.id.action_reschedule_cards:
            {
                Timber.i("CardBrowser:: Reschedule button pressed");
                long[] selectedCardIds = getSelectedCardIds();
                FunctionalInterfaces.Consumer<Integer> consumer = newDays -> CollectionTask.launchCollectionTask(DISMISS_MULTI, rescheduleCardHandler(), new TaskData(new Object[] { selectedCardIds, Collection.DismissType.RESCHEDULE_CARDS, newDays }));
                RescheduleDialog rescheduleDialog;
                if (selectedCardIds.length == 1) {
                    long cardId = selectedCardIds[0];
                    Card selected = getCol().getCard(cardId);
                    rescheduleDialog = RescheduleDialog.rescheduleSingleCard(getResources(), selected, consumer);
                } else {
                    rescheduleDialog = RescheduleDialog.rescheduleMultipleCards(getResources(), consumer, selectedCardIds.length);
                }
                showDialogFragment(rescheduleDialog);
                return true;
            }
        case R.id.action_reposition_cards:
            {
                Timber.i("CardBrowser:: Reposition button pressed");
                // Only new cards may be repositioned
                long[] cardIds = getSelectedCardIds();
                for (int i = 0; i < cardIds.length; i++) {
                    if (getCol().getCard(cardIds[i]).getQueue() != Consts.CARD_TYPE_NEW) {
                        SimpleMessageDialog dialog = SimpleMessageDialog.newInstance(getString(R.string.vague_error), getString(R.string.reposition_card_not_new_error), false);
                        showDialogFragment(dialog);
                        return false;
                    }
                }
                IntegerDialog repositionDialog = new IntegerDialog();
                repositionDialog.setArgs(getString(R.string.reposition_card_dialog_title), getString(R.string.reposition_card_dialog_message), 5);
                repositionDialog.setCallbackRunnable(days -> CollectionTask.launchCollectionTask(DISMISS_MULTI, repositionCardHandler(), new TaskData(new Object[] { cardIds, Collection.DismissType.REPOSITION_CARDS, days })));
                showDialogFragment(repositionDialog);
                return true;
            }
        case R.id.action_edit_note:
            {
                openNoteEditorForCurrentlySelectedNote();
            }
        default:
            return super.onOptionsItemSelected(item);
    }
}
Also used : AlertDialog(android.app.AlertDialog) Arrays(java.util.Arrays) Bundle(android.os.Bundle) TagsDialog(com.ichi2.anki.dialogs.TagsDialog) Deck(com.ichi2.libanki.Deck) NonNull(androidx.annotation.NonNull) ImageView(android.widget.ImageView) RangeSeekBar(com.jaygoo.widget.RangeSeekBar) ActionBar(androidx.appcompat.app.ActionBar) Decks(com.ichi2.libanki.Decks) Handler(android.os.Handler) Map(java.util.Map) JSONException(com.ichi2.utils.JSONException) OnRangeChangedListener(com.jaygoo.widget.OnRangeChangedListener) ContextCompat(androidx.core.content.ContextCompat) DUE(com.ichi2.anki.CardBrowser.Column.DUE) Upgrade(com.ichi2.upgrade.Upgrade) CREATED(com.ichi2.anki.CardBrowser.Column.CREATED) IntentFilter(android.content.IntentFilter) Set(java.util.Set) JSONObject(com.ichi2.utils.JSONObject) SearchView(androidx.appcompat.widget.SearchView) INTERVAL(com.ichi2.anki.CardBrowser.Column.INTERVAL) Nullable(androidx.annotation.Nullable) CHANGED(com.ichi2.anki.CardBrowser.Column.CHANGED) Consts(com.ichi2.libanki.Consts) CardCache(com.ichi2.anki.CardBrowser.CardCache) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) DECK(com.ichi2.anki.CardBrowser.Column.DECK) CARD(com.ichi2.anki.CardBrowser.Column.CARD) WarpLinearLayout(com.ichi2.ui.WarpLinearLayout) UPDATE_NOTE(com.ichi2.async.CollectionTask.TASK_TYPE.UPDATE_NOTE) NOTE_TYPE(com.ichi2.anki.CardBrowser.Column.NOTE_TYPE) TAGS(com.ichi2.anki.CardBrowser.Column.TAGS) SystemClock(android.os.SystemClock) RescheduleDialog(com.ichi2.anki.dialogs.RescheduleDialog) SdCardReceiver(com.ichi2.anki.receiver.SdCardReceiver) DISMISS_MULTI(com.ichi2.async.CollectionTask.TASK_TYPE.DISMISS_MULTI) Column(com.ichi2.anki.CardBrowser.Column) ArrayList(java.util.ArrayList) LAPSES(com.ichi2.anki.CardBrowser.Column.LAPSES) RENDER_BROWSER_QA(com.ichi2.async.CollectionTask.TASK_TYPE.RENDER_BROWSER_QA) SFLD(com.ichi2.anki.CardBrowser.Column.SFLD) Toast(android.widget.Toast) Menu(android.view.Menu) SimpleMessageDialog(com.ichi2.anki.dialogs.SimpleMessageDialog) REVIEWS(com.ichi2.anki.CardBrowser.Column.REVIEWS) IntegerDialog(com.ichi2.anki.dialogs.IntegerDialog) EASE(com.ichi2.anki.CardBrowser.Column.EASE) CheckResult(androidx.annotation.CheckResult) TextUtils(android.text.TextUtils) Gravity(android.view.Gravity) ArrayAdapter(android.widget.ArrayAdapter) SharedPreferences(android.content.SharedPreferences) TypedValue(android.util.TypedValue) ActivityTransitionAnimation(com.ichi2.anim.ActivityTransitionAnimation) CardBrowserOrderDialog(com.ichi2.anki.dialogs.CardBrowserOrderDialog) CardBrowser.sCardBrowserCard(com.ichi2.anki.CardBrowser.sCardBrowserCard) LinearLayout(android.widget.LinearLayout) WindowManager(android.view.WindowManager) UNDO(com.ichi2.async.CollectionTask.TASK_TYPE.UNDO) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog) Permissions(com.ichi2.utils.Permissions) FunctionalInterfaces(com.ichi2.utils.FunctionalInterfaces) CheckBox(android.widget.CheckBox) Locale(java.util.Locale) View(android.view.View) Button(android.widget.Button) TaskData(com.ichi2.async.TaskData) AdapterView(android.widget.AdapterView) RecyclerView(androidx.recyclerview.widget.RecyclerView) CardBrowserMySearchesDialog(com.ichi2.anki.dialogs.CardBrowserMySearchesDialog) TabLayout(com.google.android.material.tabs.TabLayout) SEARCH_CARDS(com.ichi2.async.CollectionTask.TASK_TYPE.SEARCH_CARDS) ANSWER(com.ichi2.anki.CardBrowser.Column.ANSWER) BroadcastReceiver(android.content.BroadcastReceiver) ViewGroup(android.view.ViewGroup) Timber(timber.log.Timber) AlertDialog(android.app.AlertDialog) Objects(java.util.Objects) List(java.util.List) TextView(android.widget.TextView) OnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener) SimpleAdapter(android.widget.SimpleAdapter) OrderListAdapter(com.ichi2.anki.widgets.OrderListAdapter) RelativeLayout(android.widget.RelativeLayout) Toolbar(androidx.appcompat.widget.Toolbar) TaskListenerWithContext(com.ichi2.async.TaskListenerWithContext) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) Snackbar(com.google.android.material.snackbar.Snackbar) Context(android.content.Context) EDITED(com.ichi2.anki.CardBrowser.Column.EDITED) Intent(android.content.Intent) HashMap(java.util.HashMap) CHECK_CARD_SELECTION(com.ichi2.async.CollectionTask.TASK_TYPE.CHECK_CARD_SELECTION) Collection(com.ichi2.libanki.Collection) TypedArray(android.content.res.TypedArray) MenuItem(android.view.MenuItem) InputMethodManager(android.view.inputmethod.InputMethodManager) HashSet(java.util.HashSet) CardsListAdapter(com.ichi2.anki.widgets.CardsListAdapter) DeckDropDownAdapter(com.ichi2.anki.widgets.DeckDropDownAdapter) WidgetStatus(com.ichi2.widget.WidgetStatus) QUESTION(com.ichi2.anki.CardBrowser.Column.QUESTION) Utils(com.ichi2.libanki.Utils) ListPopupWindow(androidx.appcompat.widget.ListPopupWindow) Iterator(java.util.Iterator) Stats(com.ichi2.libanki.stats.Stats) PopupWindow(android.widget.PopupWindow) CollectionTask(com.ichi2.async.CollectionTask) Spinner(android.widget.Spinner) KeyBoardListenerLayout(com.ichi2.ui.KeyBoardListenerLayout) Card(com.ichi2.libanki.Card) Collections(java.util.Collections) VisibleForTesting(androidx.annotation.VisibleForTesting) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) SimpleMessageDialog(com.ichi2.anki.dialogs.SimpleMessageDialog) HashMap(java.util.HashMap) Deck(com.ichi2.libanki.Deck) JSONException(com.ichi2.utils.JSONException) Intent(android.content.Intent) TaskData(com.ichi2.async.TaskData) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog) CardBrowser.sCardBrowserCard(com.ichi2.anki.CardBrowser.sCardBrowserCard) Card(com.ichi2.libanki.Card) JSONObject(com.ichi2.utils.JSONObject) RescheduleDialog(com.ichi2.anki.dialogs.RescheduleDialog) IntegerDialog(com.ichi2.anki.dialogs.IntegerDialog) Iterator(java.util.Iterator) JSONObject(com.ichi2.utils.JSONObject) ArrayAdapter(android.widget.ArrayAdapter)

Example 20 with UNDO

use of com.ichi2.async.CollectionTask.TASK_TYPE.UNDO in project AnkiChinaAndroid by ankichinateam.

the class StudyOptionsFragment method onMenuItemClick.

@SuppressWarnings("deprecation")
@Override
public boolean onMenuItemClick(MenuItem item) {
    switch(item.getItemId()) {
        case R.id.action_browser:
            {
                Timber.i("DeckPicker:: Old browser button pressed");
                getAnkiActivity().openOldCardBrowser();
                return true;
            }
        case R.id.action_undo:
            Timber.i("StudyOptionsFragment:: Undo button pressed");
            CollectionTask.launchCollectionTask(UNDO, undoListener);
            return true;
        case R.id.action_deck_options:
            Timber.i("StudyOptionsFragment:: Deck options button pressed");
            if (getCol().getDecks().isDyn(getCol().getDecks().selected())) {
                openFilteredDeckOptions();
            } else {
                Intent i = new Intent(getActivity(), DeckOptions.class);
                getActivity().startActivityForResult(i, DECK_OPTIONS);
                ActivityTransitionAnimation.slide(getActivity(), ActivityTransitionAnimation.FADE);
            }
            return true;
        case R.id.action_setting:
            Timber.i("StudyOptionsFragment:: Deck setting button pressed");
            Intent i = new Intent(getActivity(), StudySettingActivity.class);
            getActivity().startActivityForResult(i, DECK_OPTIONS);
            ActivityTransitionAnimation.slide(getActivity(), ActivityTransitionAnimation.FADE);
            return true;
        case R.id.action_custom_study:
            Timber.i("StudyOptionsFragment:: custom study button pressed");
            showCustomStudyContextMenu();
            return true;
        case R.id.action_unbury:
            Timber.i("StudyOptionsFragment:: unbury button pressed");
            getCol().getSched().unburyCardsForDeck();
            refreshInterfaceAndDecklist(true);
            item.setVisible(false);
            return true;
        case R.id.action_rebuild:
            Timber.i("StudyOptionsFragment:: rebuild cram deck button pressed");
            mProgressDialog = StyledProgressDialog.show(getActivity(), "", getResources().getString(R.string.rebuild_filtered_deck), true);
            CollectionTask.launchCollectionTask(REBUILD_CRAM, getCollectionTaskListener(true));
            return true;
        case R.id.action_empty:
            Timber.i("StudyOptionsFragment:: empty cram deck button pressed");
            mProgressDialog = StyledProgressDialog.show(getActivity(), "", getResources().getString(R.string.empty_filtered_deck), false);
            CollectionTask.launchCollectionTask(EMPTY_CRAM, getCollectionTaskListener(true));
            return true;
        case R.id.action_rename:
            ((AnkiActivity) getActivity()).renameDeckDialog(getCol().getDecks().selected());
            return true;
        case R.id.action_delete:
            getAnkiActivity().mContextMenuDid = getCol().getDecks().selected();
            ((AnkiActivity) getActivity()).confirmDeckDeletion(getCol().getDecks().selected());
            return true;
        case R.id.action_export:
            ((AnkiActivity) getActivity()).exportDeck(getCol().getDecks().selected());
            return true;
        case R.id.action_add_card:
            addNote();
            return true;
        case R.id.create_deck:
            getAnkiActivity().mContextMenuDid = getCol().getDecks().selected();
            ((AnkiActivity) getActivity()).createSubdeckDialog();
            return true;
        case // 停止/恢复
        R.id.action_suspend:
            mDeckIsStopped = deckIsStopped();
            if (mDeckIsStopped) {
                customDialog = new CustomStyleDialog.Builder(getAnkiActivity()).setTitle("恢复学习").setMessage("恢复学习后将每天新卡数和复习数值调整成默认值,请确认是否开始学习").setPositiveButton("确定", (dialog, which) -> {
                    resumeDeckStudy();
                    dialog.dismiss();
                }).setNegativeButton("取消", (dialog, which) -> dialog.dismiss()).create();
            } else {
                customDialog = new CustomStyleDialog.Builder(getAnkiActivity()).setTitle("停止学习").setMessage("暂停学习将会自动把每天新卡数和复习数调整为零,适用于有事暂停一两周不学习,若该记忆库学习的时长不超过2个月,又暂停了30天未学习,建议重设进度,重新开始学习").setPositiveButton("确定", (dialog, which) -> {
                    stopDeckStudy();
                    dialog.dismiss();
                }).setNegativeButton("取消", (dialog, which) -> dialog.dismiss()).create();
            }
            customDialog.show();
            return true;
        case // 重设学习进度
        R.id.action_reset_card_progress:
            customDialog = new CustomStyleDialog.Builder(getAnkiActivity()).setTitle("重设学习进度").setMessage("重设学习进度后,该记忆库的所有卡片学习记录都会被清除,请谨慎操作").setPositiveButton("确定", (dialog, which) -> {
                CollectionTask.launchCollectionTask(RESET_DECK, new ResetCardHandler(StudyOptionsFragment.this), new TaskData(new Object[] { "deck:\"" + getCol().getDecks().current().getString("name") + "\" " }));
                dialog.dismiss();
            }).setNegativeButton("取消", (dialog, which) -> dialog.dismiss()).create();
            customDialog.show();
            return true;
        default:
            return false;
    }
}
Also used : DividerItemDecoration(androidx.recyclerview.widget.DividerItemDecoration) Bundle(android.os.Bundle) TypeToken(com.google.gson.reflect.TypeToken) Deck(com.ichi2.libanki.Deck) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) WindowManager(android.view.WindowManager) ImageView(android.widget.ImageView) ColorDrawable(android.graphics.drawable.ColorDrawable) Drawable(android.graphics.drawable.Drawable) Maps(java8.util.Maps) KEY_STOPPED(com.ichi2.anki.StudySettingActivity.KEY_STOPPED) DeckInfoListAdapter(com.ichi2.anki.widgets.DeckInfoListAdapter) Decks(com.ichi2.libanki.Decks) Gson(com.google.gson.Gson) Locale(java.util.Locale) Handler(android.os.Handler) DeckConfig(com.ichi2.libanki.DeckConfig) Map(java.util.Map) Fragment(androidx.fragment.app.Fragment) View(android.view.View) Button(android.widget.Button) TaskData(com.ichi2.async.TaskData) RecyclerView(androidx.recyclerview.widget.RecyclerView) REQUEST_BROWSE_CARDS(com.ichi2.anki.DeckPicker.REQUEST_BROWSE_CARDS) TabLayout(com.google.android.material.tabs.TabLayout) TYPE_LIFE(com.ichi2.libanki.stats.Stats.AxisType.TYPE_LIFE) SHOW_STUDYOPTIONS(com.ichi2.anki.DeckPicker.SHOW_STUDYOPTIONS) Set(java.util.Set) FragmentTransaction(androidx.fragment.app.FragmentTransaction) DisplayMetrics(android.util.DisplayMetrics) ViewGroup(android.view.ViewGroup) Timber(timber.log.Timber) DeckPickerContextMenu(com.ichi2.anki.dialogs.DeckPickerContextMenu) List(java.util.List) Nullable(androidx.annotation.Nullable) TextView(android.widget.TextView) NextCardHandler(com.ichi2.anki.AbstractFlashcardViewer.NextCardHandler) ALL_DECKS_ID(com.ichi2.libanki.stats.Stats.ALL_DECKS_ID) CompatHelper(com.ichi2.compat.CompatHelper) Toolbar(androidx.appcompat.widget.Toolbar) RelativeLayout(android.widget.RelativeLayout) TaskListenerWithContext(com.ichi2.async.TaskListenerWithContext) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) Window(android.view.Window) Snackbar(com.google.android.material.snackbar.Snackbar) DialogFragment(androidx.fragment.app.DialogFragment) KEY_SHOW_TTS_ICON(com.ichi2.libanki.Consts.KEY_SHOW_TTS_ICON) Context(android.content.Context) TaskListener(com.ichi2.async.TaskListener) Dialog(android.app.Dialog) Intent(android.content.Intent) StepsPreference.convertToJSON(com.ichi2.preferences.StepsPreference.convertToJSON) HashMap(java.util.HashMap) Collection(com.ichi2.libanki.Collection) StyledProgressDialog(com.ichi2.themes.StyledProgressDialog) PixelFormat(android.graphics.PixelFormat) Editable(android.text.Editable) TypedArray(android.content.res.TypedArray) MenuItem(android.view.MenuItem) TASK_TYPE(com.ichi2.async.CollectionTask.TASK_TYPE) ArrayList(java.util.ArrayList) JSONArray(com.ichi2.utils.JSONArray) Menu(android.view.Menu) Utils(com.ichi2.libanki.Utils) AbstractDeckTreeNode(com.ichi2.libanki.sched.AbstractDeckTreeNode) Stats(com.ichi2.libanki.stats.Stats) LayoutInflater(android.view.LayoutInflater) CollectionTask(com.ichi2.async.CollectionTask) Color(android.graphics.Color) Gravity(android.view.Gravity) SharedPreferences(android.content.SharedPreferences) TypedValue(android.util.TypedValue) TreeMap(java.util.TreeMap) KEY_MIND_MODE(com.ichi2.anki.StudySettingActivity.KEY_MIND_MODE) CustomStudyDialog(com.ichi2.anki.dialogs.CustomStudyDialog) DeckPicker.fadeOut(com.ichi2.anki.DeckPicker.fadeOut) Activity(android.app.Activity) ActivityTransitionAnimation(com.ichi2.anim.ActivityTransitionAnimation) DeckPicker.fadeIn(com.ichi2.anki.DeckPicker.fadeIn) STUDY_SETTING(com.ichi2.anki.StudySettingActivity.STUDY_SETTING) EditText(android.widget.EditText) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) Resources(android.content.res.Resources) Intent(android.content.Intent) TaskData(com.ichi2.async.TaskData)

Aggregations

Collection (com.ichi2.libanki.Collection)22 Card (com.ichi2.libanki.Card)15 JSONObject (com.ichi2.utils.JSONObject)13 Intent (android.content.Intent)8 JSONException (com.ichi2.utils.JSONException)7 ArrayList (java.util.ArrayList)7 MenuItem (android.view.MenuItem)6 View (android.view.View)6 VisibleForTesting (androidx.annotation.VisibleForTesting)6 Context (android.content.Context)5 SharedPreferences (android.content.SharedPreferences)5 Bundle (android.os.Bundle)5 Menu (android.view.Menu)5 WindowManager (android.view.WindowManager)5 TextView (android.widget.TextView)5 NonNull (androidx.annotation.NonNull)5 Nullable (androidx.annotation.Nullable)5 SearchView (androidx.appcompat.widget.SearchView)5 MaterialDialog (com.afollestad.materialdialogs.MaterialDialog)5 Snackbar (com.google.android.material.snackbar.Snackbar)5