Search in sources :

Example 1 with Model

use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.

the class AbstractFlashcardViewer method updateCard.

private void updateCard(final String newContent) {
    Timber.d("updateCard()");
    mCacheContent = newContent;
    mUseTimerDynamicMS = 0;
    // Add CSS for font color and font size
    if (mCurrentCard == null) {
        processCardAction(cardWebView -> cardWebView.getSettings().setDefaultFontSize(calculateDynamicFontSize(newContent)));
    }
    if (sDisplayAnswer) {
        addAnswerSounds(newContent);
    } else {
        // reset sounds each time first side of card is displayed, which may happen repeatedly without ever
        // leaving the card (such as when edited)
        mSoundPlayer.resetSounds();
        mAnswerSoundsAdded = false;
        mSoundPlayer.addSounds(mBaseUrl, newContent, SoundSide.QUESTION);
        if (mUseTimer && !mAnswerSoundsAdded && getConfigForCurrentCard().optBoolean("autoplay", false)) {
            addAnswerSounds(mCurrentCard.a());
        }
    }
    String content = Sound.expandSounds(mBaseUrl, newContent);
    content = CardAppearance.fixBoldStyle(content);
    Timber.v("content card = \n %s", content);
    String style = mCardAppearance.getStyle();
    Timber.v("::style:: / %s", style);
    // CSS class for card-specific styling
    String cardClass = mCardAppearance.getCardClass(mCurrentCard.getOrd() + 1, Themes.getCurrentTheme(this));
    if (Template.textContainsMathjax(content)) {
        cardClass += " mathjax-needs-to-render";
    }
    if (isInNightMode()) {
        if (!mCardAppearance.hasUserDefinedNightMode(mCurrentCard)) {
            content = HtmlColors.invertColors(content);
        }
    }
    content = CardAppearance.convertSmpToHtmlEntity(content);
    SharedPreferences prefs = AnkiDroidApp.getSharedPrefs(this);
    String localViewSettingStr = prefs.getString(Consts.KEY_LOCAL_LAYOUT_CONFIG, "");
    boolean dark = false;
    if (AnkiDroidApp.getSharedPrefs(this).getBoolean("invertedColors", false)) {
        int theme = Integer.parseInt(prefs.getString("nightTheme", "0"));
        dark = theme == THEME_NIGHT_DARK || theme == THEME_NIGHT_BLACK;
    }
    if (mCurrentCSS.isEmpty() || mCurrentCSSModelID != mCurrentCard.model().getLong("id")) {
        mCurrentCSSModelID = mCurrentCard.model().getLong("id");
        Timber.i("find new model id css %s", mCurrentCSS);
        if (localViewSettingStr != null && !localViewSettingStr.isEmpty()) {
            try {
                JSONObject viewSetting = new JSONObject(localViewSettingStr);
                JSONObject currentModelSetting = viewSetting.getJSONObject(String.valueOf(mCurrentCSSModelID));
                if (currentModelSetting != null) {
                    mCurrentCSS = convertJson2Css(currentModelSetting, false);
                } else {
                    mCurrentCSS = "";
                }
            } catch (Exception e) {
                e.printStackTrace();
                mCurrentCSS = "";
            }
        }
    }
    Timber.i("now theme is dark:%s", dark);
    if (!dark) {
        if (!mCurrentCSS.isEmpty()) {
            Matcher bgMatcher = Pattern.compile("background-color:(.+?);").matcher(mCurrentCSS);
            Window window = getWindow();
            if (bgMatcher.find()) {
                String fld1 = bgMatcher.group(1).trim();
                if (shouldChangeToolbarBgLikeCss2()) {
                    findViewById(R.id.toolbar).setBackgroundColor(Color.parseColor(fld1));
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        window.setStatusBarColor(Color.parseColor(fld1));
                    }
                }
                mCardWebView.setBackgroundColor(Color.parseColor(fld1));
                findViewById(R.id.bottom_area_layout).setBackgroundColor(Color.parseColor(fld1));
            } else {
                if (shouldChangeToolbarBgLikeCss2()) {
                    int[] attrs = new int[] { R.attr.reviewStatusBarColor };
                    TypedArray ta = obtainStyledAttributes(attrs);
                    findViewById(R.id.toolbar).setBackground(ta.getDrawable(0));
                    ta.recycle();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        window.setStatusBarColor(Themes.getColorFromAttr(this, getStatusBarColorAttr()));
                    }
                }
                mCardWebView.setBackgroundColor(Color.WHITE);
                findViewById(R.id.bottom_area_layout).setBackgroundColor(Color.TRANSPARENT);
            }
        } else {
            if (shouldChangeToolbarBgLikeCss2()) {
                int[] attrs = new int[] { R.attr.reviewStatusBarColor };
                TypedArray ta = obtainStyledAttributes(attrs);
                findViewById(R.id.toolbar).setBackground(ta.getDrawable(0));
                ta.recycle();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    Window window = getWindow();
                    window.setStatusBarColor(Themes.getColorFromAttr(this, getStatusBarColorAttr()));
                }
            }
            mCardWebView.setBackgroundColor(Color.WHITE);
            findViewById(R.id.bottom_area_layout).setBackgroundColor(Color.TRANSPARENT);
        }
    }
    // if (mCurrentCSS.isEmpty()) {//保存的配置文件没有,则直接找默认的css
    // mCurrentCSS = mCurrentCard.css().replace("<style>", "").replace("</style>", "");
    // }
    mCardContent = mCardTemplate.replace("::content::", content).replace("::style::", style).replace("::class::", cardClass).replace("::style2::", mCurrentCSS).replace("::class2::", sDisplayAnswer ? "ck-back" : "ck-front");
    Timber.d("base url = %s", mBaseUrl);
    Timber.v("::content:: / %s", content);
    Timber.v("::style2:: / %s", mCurrentCSS);
    if (AnkiDroidApp.getSharedPrefs(this).getBoolean("html_javascript_debugging", false)) {
        try {
            try (FileOutputStream f = new FileOutputStream(new File(CollectionHelper.getCurrentAnkiDroidDirectory(this), "card.html"))) {
                f.write(mCardContent.getBytes());
            }
        } catch (IOException e) {
            Timber.d(e, "failed to save card");
        }
    }
    fillFlashcard();
    if (!mConfigurationChanged) {
        playSoundsVIP(false);
    }
}
Also used : Window(android.view.Window) SharedPreferences(android.content.SharedPreferences) Matcher(java.util.regex.Matcher) IOException(java.io.IOException) SuppressLint(android.annotation.SuppressLint) JSONException(com.ichi2.utils.JSONException) IOException(java.io.IOException) ActivityNotFoundException(android.content.ActivityNotFoundException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JSONObject(com.ichi2.utils.JSONObject) TypedArray(android.content.res.TypedArray) FileOutputStream(java.io.FileOutputStream) File(java.io.File)

Example 2 with Model

use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.

the class AbstractFlashcardViewer method getAnswerFormat.

/**
 * getAnswerFormat returns the answer part of this card's template as entered by user, without any parsing
 */
public String getAnswerFormat() {
    JSONObject model = mCurrentCard.model();
    JSONObject template;
    if (model.getInt("type") == Consts.MODEL_STD) {
        template = model.getJSONArray("tmpls").getJSONObject(mCurrentCard.getOrd());
    } else {
        template = model.getJSONArray("tmpls").getJSONObject(0);
    }
    return template.getString("afmt");
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 3 with Model

use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.

the class ContentProviderTest method testInsertAndRemoveNote.

/**
 * Check that inserting and removing a note into default deck works as expected
 */
@Test
public void testInsertAndRemoveNote() {
    // Get required objects for test
    final ContentResolver cr = InstrumentationRegistry.getInstrumentation().getTargetContext().getContentResolver();
    // Add the note
    ContentValues values = new ContentValues();
    values.put(FlashCardsContract.Note.MID, mModelId);
    values.put(FlashCardsContract.Note.FLDS, Utils.joinFields(TEST_NOTE_FIELDS));
    values.put(FlashCardsContract.Note.TAGS, TEST_TAG);
    Uri newNoteUri = cr.insert(FlashCardsContract.Note.CONTENT_URI, values);
    assertNotNull("Check that URI returned from addNewNote is not null", newNoteUri);
    // test that the changes are physically saved to the DB
    final Collection col = reopenCol();
    // Check that it looks as expected
    assertNotNull("check note URI path", newNoteUri.getLastPathSegment());
    Note addedNote = new Note(col, Long.parseLong(newNoteUri.getLastPathSegment()));
    addedNote.load();
    assertArrayEquals("Check that fields were set correctly", addedNote.getFields(), TEST_NOTE_FIELDS);
    assertEquals("Check that tag was set correctly", TEST_TAG, addedNote.getTags().get(0));
    JSONObject model = col.getModels().get(mModelId);
    assertNotNull("Check model", model);
    int expectedNumCards = model.getJSONArray("tmpls").length();
    assertEquals("Check that correct number of cards generated", expectedNumCards, addedNote.numberOfCards());
    // Now delete the note
    cr.delete(newNoteUri, null, null);
    try {
        addedNote.load();
        fail("Expected RuntimeException to be thrown when deleting note");
    } catch (RuntimeException e) {
    // Expect RuntimeException to be thrown when loading deleted note
    }
}
Also used : ContentValues(android.content.ContentValues) JSONObject(com.ichi2.utils.JSONObject) Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Uri(android.net.Uri) ContentResolver(android.content.ContentResolver) Test(org.junit.Test)

Example 4 with Model

use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.

the class ContentProviderTest method setUp.

/**
 * Initially create one note for each model.
 */
@Before
public void setUp() throws Exception {
    Log.i(AnkiDroidApp.TAG, "setUp()");
    mCreatedNotes = new ArrayList<>();
    final Collection col = getCol();
    // We have parameterized the "schedVersion" variable, if we are on an emulator
    // (so it is safe) we will try to run with multiple scheduler versions
    tearDown = false;
    if (InstrumentedTest.isEmulator()) {
        col.changeSchedulerVer(schedVersion);
    } else {
        if (schedVersion == 1) {
            assumeThat(col.getSched().getName(), is("std"));
        } else {
            assumeThat(col.getSched().getName(), is("std2"));
        }
    }
    tearDown = true;
    // Do not teardown if setup was aborted
    // Add a new basic model that we use for testing purposes (existing models could potentially be corrupted)
    Model model = StdModels.basicModel.add(col, BASIC_MODEL_NAME);
    mModelId = model.getLong("id");
    ArrayList<String> fields = Models.fieldNames(model);
    // Use the names of the fields as test values for the notes which will be added
    mDummyFields = fields.toArray(new String[0]);
    // create test decks and add one note for every deck
    mNumDecksBeforeTest = col.getDecks().count();
    for (String fullName : TEST_DECKS) {
        String[] path = Decks.path(fullName);
        String partialName = "";
        /* Looping over all parents of full name. Adding them to
             * mTestDeckIds ensures the deck parents decks get deleted
             * too at tear-down.
             */
        for (String s : path) {
            partialName += s;
            /* If parent already exists, don't add the deck, so
                 * that we are sure it won't get deleted at
                 * set-down, */
            if (col.getDecks().byName(partialName) != null) {
                continue;
            }
            long did = col.getDecks().id(partialName);
            mTestDeckIds.add(did);
            mCreatedNotes.add(setupNewNote(col, mModelId, did, mDummyFields, TEST_TAG));
            partialName += "::";
        }
    }
    // Add a note to the default deck as well so that testQueryNextCard() works
    mCreatedNotes.add(setupNewNote(col, mModelId, 1, mDummyFields, TEST_TAG));
}
Also used : Model(com.ichi2.libanki.Model) Collection(com.ichi2.libanki.Collection) Before(org.junit.Before)

Example 5 with Model

use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.

the class ContentProviderTest method testInsertField.

/**
 * Check that inserting and removing a note into default deck works as expected
 */
@Test
public void testInsertField() throws Exception {
    // Get required objects for test
    final ContentResolver cr = InstrumentationRegistry.getInstrumentation().getTargetContext().getContentResolver();
    Collection col = getCol();
    Model model = StdModels.basicModel.add(col, BASIC_MODEL_NAME);
    long modelId = model.getLong("id");
    JSONArray initialFieldsArr = model.getJSONArray("flds");
    int initialFieldCount = initialFieldsArr.length();
    Uri noteTypeUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, modelId);
    ContentValues insertFieldValues = new ContentValues();
    insertFieldValues.put(FlashCardsContract.Model.FIELD_NAME, TEST_FIELD_NAME);
    Uri fieldUri = cr.insert(Uri.withAppendedPath(noteTypeUri, "fields"), insertFieldValues);
    assertNotNull("Check field uri", fieldUri);
    // Ensure that the changes are physically saved to the DB
    col = reopenCol();
    model = col.getModels().get(modelId);
    // Test the field is as expected
    long fieldId = ContentUris.parseId(fieldUri);
    assertEquals("Check field id", initialFieldCount, fieldId);
    assertNotNull("Check model", model);
    JSONArray fldsArr = model.getJSONArray("flds");
    assertEquals("Check fields length", initialFieldCount + 1, fldsArr.length());
    assertEquals("Check last field name", TEST_FIELD_NAME, fldsArr.getJSONObject(fldsArr.length() - 1).optString("name", ""));
    col.getModels().rem(model);
}
Also used : ContentValues(android.content.ContentValues) Model(com.ichi2.libanki.Model) JSONArray(com.ichi2.utils.JSONArray) Collection(com.ichi2.libanki.Collection) Uri(android.net.Uri) ContentResolver(android.content.ContentResolver) Test(org.junit.Test)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)124 Model (com.ichi2.libanki.Model)95 Test (org.junit.Test)82 JSONArray (com.ichi2.utils.JSONArray)79 Collection (com.ichi2.libanki.Collection)53 ArrayList (java.util.ArrayList)48 Note (com.ichi2.libanki.Note)40 RobolectricTest (com.ichi2.anki.RobolectricTest)38 JSONException (com.ichi2.utils.JSONException)32 Intent (android.content.Intent)30 Card (com.ichi2.libanki.Card)27 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)26 HashMap (java.util.HashMap)22 Bundle (android.os.Bundle)20 NonNull (androidx.annotation.NonNull)20 SuppressLint (android.annotation.SuppressLint)16 View (android.view.View)16 ConfirmationDialog (com.ichi2.anki.dialogs.ConfirmationDialog)15 IOException (java.io.IOException)15 Nullable (androidx.annotation.Nullable)14