Search in sources :

Example 11 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class ContentProviderTest method testSuspendCard.

/**
 * Test suspending a card through the ReviewInfo endpoint
 */
@Test
public void testSuspendCard() {
    // get the first card due
    // ----------------------
    Collection col = getCol();
    Card card = getFirstCardFromScheduler(col);
    // verify that the card is not already suspended
    Assert.assertNotEquals("Card is not suspended before test", Consts.QUEUE_TYPE_SUSPENDED, card.getQueue());
    // retain the card id, we will lookup the card after the update
    long cardId = card.getId();
    // suspend it through the API
    // --------------------------
    ContentResolver cr = InstrumentationRegistry.getInstrumentation().getTargetContext().getContentResolver();
    Uri reviewInfoUri = FlashCardsContract.ReviewInfo.CONTENT_URI;
    ContentValues values = new ContentValues();
    long noteId = card.note().getId();
    int cardOrd = card.getOrd();
    int suspend = 1;
    values.put(FlashCardsContract.ReviewInfo.NOTE_ID, noteId);
    values.put(FlashCardsContract.ReviewInfo.CARD_ORD, cardOrd);
    values.put(FlashCardsContract.ReviewInfo.SUSPEND, suspend);
    int updateCount = cr.update(reviewInfoUri, values, null, null);
    assertEquals("Check if update returns 1", 1, updateCount);
    // verify that it did get suspended
    // --------------------------------
    Card cardAfterUpdate = col.getCard(cardId);
    assertEquals("Card is suspended", Consts.QUEUE_TYPE_SUSPENDED, cardAfterUpdate.getQueue());
    // cleanup, unsuspend card and reschedule
    // --------------------------------------
    col.getSched().unsuspendCards(new long[] { cardId });
    col.reset();
}
Also used : ContentValues(android.content.ContentValues) Collection(com.ichi2.libanki.Collection) Uri(android.net.Uri) Card(com.ichi2.libanki.Card) ContentResolver(android.content.ContentResolver) Test(org.junit.Test)

Example 12 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class NoteEditor method updateCards.

/**
 * Update the list of card templates for current note type
 */
private void updateCards(JSONObject model) {
    Timber.d("updateCards()");
    JSONArray tmpls = model.getJSONArray("tmpls");
    StringBuilder cardsList = new StringBuilder();
    // Build comma separated list of card names
    Timber.d("updateCards() template count is %s", tmpls.length());
    for (int i = 0; i < tmpls.length(); i++) {
        String name = tmpls.getJSONObject(i).optString("name");
        // If more than one card, and we have an existing card, underline existing card
        if (!mAddNote && tmpls.length() > 1 && model == mEditorNote.model() && mCurrentEditedCard != null && mCurrentEditedCard.template().optString("name").equals(name)) {
            name = "<u>" + name + "</u>";
        }
        cardsList.append(name);
        if (i < tmpls.length() - 1) {
            cardsList.append(", ");
        }
    }
    // Make cards list red if the number of cards is being reduced
    if (!mAddNote && tmpls.length() < mEditorNote.model().getJSONArray("tmpls").length()) {
        cardsList = new StringBuilder("<font color='red'>" + cardsList + "</font>");
    }
    mCardsButton.setText(CompatHelper.getCompat().fromHtml(getResources().getString(R.string.CardEditorCards, cardsList.toString())));
}
Also used : JSONArray(com.ichi2.utils.JSONArray) SuppressLint(android.annotation.SuppressLint)

Example 13 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class NoteEditor method saveNote.

@VisibleForTesting
void saveNote() {
    final Resources res = getResources();
    if (mSelectedTags == null) {
        mSelectedTags = new ArrayList<>(0);
    }
    // treat add new note and edit existing note independently
    if (mAddNote) {
        // DEFECT: This does not block addition if cloze transpositions are in non-cloze fields.
        if (isClozeType() && !hasClozeDeletions()) {
            displayErrorSavingNote();
            return;
        }
        // load all of the fields into the note
        for (FieldEditText f : mEditFields) {
            updateField(f);
        }
        // Save deck to model
        mEditorNote.model().put("did", mCurrentDid);
        // Save tags to model
        mEditorNote.setTagsFromStr(tagsAsString(mSelectedTags));
        JSONArray tags = new JSONArray();
        for (String t : mSelectedTags) {
            tags.put(t);
        }
        getCol().getModels().current().put("tags", tags);
        getCol().getModels().setChanged();
        mReloadRequired = true;
        CollectionTask.launchCollectionTask(ADD_NOTE, saveNoteHandler(), new TaskData(mEditorNote));
    } else {
        // Check whether note type has been changed
        final Model newModel = getCurrentlySelectedModel();
        final Model oldModel = (mCurrentEditedCard == null) ? null : mCurrentEditedCard.model();
        File target = new File(FileUtil.createTmpDir(this), mCurrentEditedCard.getId() + ".wav");
        if (target.exists()) {
            Timber.i("editing card audio is exists,delete it");
            target.delete();
        }
        if (!newModel.equals(oldModel)) {
            mReloadRequired = true;
            if (mModelChangeCardMap.size() < mEditorNote.numberOfCards() || mModelChangeCardMap.containsValue(null)) {
                // If cards will be lost via the new mapping then show a confirmation dialog before proceeding with the change
                ConfirmationDialog dialog = new ConfirmationDialog();
                dialog.setArgs(res.getString(R.string.confirm_map_cards_to_nothing));
                Runnable confirm = () -> {
                    // Bypass the check once the user confirms
                    changeNoteTypeWithErrorHandling(oldModel, newModel);
                };
                dialog.setConfirm(confirm);
                showDialogFragment(dialog);
            } else {
                // Otherwise go straight to changing note type
                changeNoteTypeWithErrorHandling(oldModel, newModel);
            }
            return;
        }
        // Regular changes in note content
        boolean modified = false;
        // changed did? this has to be done first as remFromDyn() involves a direct write to the database
        if (mCurrentEditedCard != null && mCurrentEditedCard.getDid() != mCurrentDid) {
            mReloadRequired = true;
            // remove card from filtered deck first (if relevant)
            getCol().getSched().remFromDyn(new long[] { mCurrentEditedCard.getId() });
            // refresh the card object to reflect the database changes in remFromDyn()
            mCurrentEditedCard.load();
            // also reload the note object
            mEditorNote = mCurrentEditedCard.note();
            // then set the card ID to the new deck
            mCurrentEditedCard.setDid(mCurrentDid);
            modified = true;
        }
        // now load any changes to the fields from the form
        for (FieldEditText f : mEditFields) {
            modified = modified | updateField(f);
        }
        // added tag?
        for (String t : mSelectedTags) {
            modified = modified || !mEditorNote.hasTag(t);
        }
        // removed tag?
        modified = modified || mEditorNote.getTags().size() > mSelectedTags.size();
        if (modified) {
            mEditorNote.setTagsFromStr(tagsAsString(mSelectedTags));
            mChanged = true;
        }
        closeNoteEditor();
    }
}
Also used : JSONArray(com.ichi2.utils.JSONArray) Model(com.ichi2.libanki.Model) Resources(android.content.res.Resources) File(java.io.File) TaskData(com.ichi2.async.TaskData) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 14 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class DeckOptions method registerExternalStorageListener.

/**
 * finish when sd card is ejected
 */
private void registerExternalStorageListener() {
    if (mUnmountReceiver == null) {
        mUnmountReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                if (SdCardReceiver.MEDIA_EJECT.equals(intent.getAction())) {
                    finish();
                }
            }
        };
        IntentFilter iFilter = new IntentFilter();
        iFilter.addAction(SdCardReceiver.MEDIA_EJECT);
        registerReceiver(mUnmountReceiver, iFilter);
    }
}
Also used : TaskListenerWithContext(com.ichi2.async.TaskListenerWithContext) Context(android.content.Context) IntentFilter(android.content.IntentFilter) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) BroadcastReceiver(android.content.BroadcastReceiver)

Example 15 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class CardBrowser method onActivityResult.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // FIXME:
    Timber.d("onActivityResult(requestCode=%d, resultCode=%d)", requestCode, resultCode);
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == DeckPicker.RESULT_DB_ERROR) {
        closeCardBrowser(DeckPicker.RESULT_DB_ERROR);
    }
    if (requestCode == EDIT_CARD && resultCode != RESULT_CANCELED) {
        Timber.i("CardBrowser:: CardBrowser: Saving card...");
        CollectionTask.launchCollectionTask(UPDATE_NOTE, updateCardHandler(), new TaskData(sCardBrowserCard, false));
    } else if (requestCode == ADD_NOTE && resultCode == RESULT_OK) {
        if (mSearchView != null) {
            mSearchTerms = mSearchView.getQuery().toString();
            searchCards();
        } else {
            Timber.w("Note was added from browser and on return mSearchView == null");
        }
    }
    // Previewing can now perform an "edit", so it can pass on a reloadRequired
    if (requestCode == PREVIEW_CARDS && data != null && (data.getBooleanExtra("reloadRequired", false) || data.getBooleanExtra("noteChanged", false))) {
        searchCards();
        if (getReviewerCardId() == mCurrentCardId) {
            mReloadRequired = true;
        }
    }
    if (requestCode == EDIT_CARD && data != null && (data.getBooleanExtra("reloadRequired", false) || data.getBooleanExtra("noteChanged", false))) {
        // if reloadRequired or noteChanged flag was sent from note editor then reload card list
        searchCards();
        // in use by reviewer?
        if (getReviewerCardId() == mCurrentCardId) {
            mReloadRequired = true;
        }
    }
    // maybe the availability of undo changed
    invalidateOptionsMenu();
}
Also used : TaskData(com.ichi2.async.TaskData)

Aggregations

Card (com.ichi2.libanki.Card)222 Test (org.junit.Test)212 Collection (com.ichi2.libanki.Collection)179 Note (com.ichi2.libanki.Note)173 RobolectricTest (com.ichi2.anki.RobolectricTest)168 JSONObject (com.ichi2.utils.JSONObject)114 JSONArray (com.ichi2.utils.JSONArray)80 DeckConfig (com.ichi2.libanki.DeckConfig)72 ArrayList (java.util.ArrayList)48 NonNull (androidx.annotation.NonNull)33 Deck (com.ichi2.libanki.Deck)32 Intent (android.content.Intent)29 JSONException (com.ichi2.utils.JSONException)27 Model (com.ichi2.libanki.Model)26 Context (android.content.Context)23 SuppressLint (android.annotation.SuppressLint)22 Cursor (android.database.Cursor)22 HashMap (java.util.HashMap)21 Matchers.containsString (org.hamcrest.Matchers.containsString)20 List (java.util.List)17