use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class AbstractFlashcardViewer method readCardText.
private void readCardText(final Card card, final SoundSide cardSide) {
final String cardSideContent;
if (!cardContentIsEmpty() && ((sDisplayAnswer && mFinalLoadAnswer.isEmpty()) || (!sDisplayAnswer && mFinalLoadQuestion.isEmpty()))) {
mainHandler.postDelayed(() -> {
showProgressBar();
Toast.makeText(AbstractFlashcardViewer.this, "卡牌加载中,网络不佳", Toast.LENGTH_SHORT).show();
}, 3000);
nNeedSpeakFinalRenderContent = true;
if (!fetchingRenderContent) {
fetchWebViewRenderContent(mCardWebView);
}
return;
}
mainHandler.removeCallbacksAndMessages(null);
hideProgressBar();
// 在这里获取最后的内容
cardSideContent = cardSide == SoundSide.QUESTION ? mFinalLoadQuestion : mFinalLoadAnswer;
Timber.i("finally i wanna say:%s,showing answer:%s", cardSideContent, sDisplayAnswer);
// 如果不是设置了离线模式且当前没网时,且非强制离线模式,则默认使用在线模式
if (AnkiDroidApp.getSharedPrefs(this).getBoolean(KEY_SELECT_ONLINE_SPEAK_ENGINE, false) && !mOfflineSpeakingForOnce) {
// 使用在线语音引擎
File target = new File(FileUtil.createTmpDir(this), card.getId() + "-" + cardSide + ".wav");
Timber.i("target audio :%s", target.getAbsolutePath());
if (target.exists()) {
Timber.i("target audio is exists,play it now");
mSoundPlayer.playSound(target.getAbsolutePath(), mp -> mOnlineSpeaking = false);
mOnlineSpeaking = true;
speakingHandler.postDelayed(speakingRunnable, 300);
return;
}
if (!isNetworkAvailable(AbstractFlashcardViewer.this)) {
CustomStyleDialog customStyleDialog = new CustomStyleDialog.Builder(AbstractFlashcardViewer.this).setCustomLayout(R.layout.dialog_common_custom_next).setTitle("在线朗读需联网!").centerTitle().setMessage("没有网络时可以点下方按钮切换成本地引擎").setPositiveButton("切换本地引擎", (dialog, which) -> {
dialog.dismiss();
AnkiDroidApp.getSharedPrefs(this).edit().putBoolean(KEY_SELECT_ONLINE_SPEAK_ENGINE, false).apply();
}).create();
customStyleDialog.show();
return;
}
getAccount().getToken(this, new MyAccount.TokenCallback() {
@Override
public void onSuccess(String token) {
mCacheToken = token;
// if (mFreeOnlineEngineCount != -10086) {
// if (mFreeOnlineEngineCount > 0) {
// String voice=ReadText.getAzureLanguage(card.getDid(), card.getOrd(), cardSide);
// if (voice.isEmpty()) {
// //选择语言
// CustomStyleDialog d = new CustomStyleDialog.Builder(AbstractFlashcardViewer.this)
// .setCustomLayout(R.layout.dialog_common_custom_next)
// .setTitle("首次朗读,请设置语言")
// .centerTitle()
// .setMessage("设置语言后,朗读效果更优,还可以选择是否自动朗读。")
// .setPositiveButton("前往设置", (dialog, which) -> {
// dialog.dismiss();
// SpeakSettingActivity.OpenSpeakSetting(card.getId(), card.getDid(), AbstractFlashcardViewer.this);
// }) .create();
// d.show();
// return;
// }
List<Pair<String, String>> texts = splitAry(cardSideContent, 59, String.valueOf(card.getId()), cardSide);
Map<String, String> params = new HashMap<>();
params.put(SpeechSynthesizer.PARAM_SPEED, String.valueOf(ReadText.getSpeechRate(mCurrentCard.getDid(), mCurrentCard.getOrd()) * 5));
synthesizer.setParams(params);
int result = synthesizer.batchSpeak(texts);
checkResult(result, "speak");
//
// } else {
// CustomStyleDialog customStyleDialog = new CustomStyleDialog.Builder(AbstractFlashcardViewer.this)
// .setCustomLayout(R.layout.dialog_common_custom_next)
// .setTitle("在线朗读次数已用完")
// .centerTitle()
// .setMessage("请前往充值在线朗读次数,学霸用户可以切换离线引擎,不限朗读次数")
// .setPositiveButton("前往充值", (dialog, which) -> {
// dialog.dismiss();
// WebViewActivity.openUrlInApp(AbstractFlashcardViewer.this, String.format(mBuyOnlineEngineUrl, token, BuildConfig.VERSION_NAME), token, REFRESH_VOICE_INFO);
// }).setNegativeButton("使用离线引擎", (dialog, which) -> {
// dialog.dismiss();
// AnkiDroidApp.getSharedPrefs(AbstractFlashcardViewer.this).edit().putBoolean(KEY_SELECT_ONLINE_SPEAK_ENGINE, false).apply();
// })
//
// .create();
//
// customStyleDialog.show();
// }
// } else {
// updateOnlineVoiceInfo(token);
// }
}
@Override
public void onFail(String message) {
Timber.e("need login while using online speak engine ");
Toast.makeText(AbstractFlashcardViewer.this, "当前未使用Anki记忆卡账号登录,无法使用在线语音引擎", Toast.LENGTH_SHORT).show();
Intent myAccount = new Intent(AbstractFlashcardViewer.this, MyAccount.class);
myAccount.putExtra("notLoggedIn", true);
startActivityForResultWithAnimation(myAccount, REFRESH_VOICE_INFO, ActivityTransitionAnimation.FADE);
}
});
speakingHandler.postDelayed(speakingRunnable, 300);
return;
}
mOfflineSpeakingForOnce = false;
String clozeReplacement = this.getString(R.string.reviewer_tts_cloze_spoken_replacement);
ReadText.readCardSide(cardSide, cardSideContent, card.getId(), getDeckIdForCard(card), card.getOrd(), clozeReplacement, true);
speakingHandler.postDelayed(speakingRunnable, 300);
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class AbstractFlashcardViewer method requireApiVersion.
/**
* Supplied api version must be equal to current api version to call mark card, toggle flag functions etc.
*/
private boolean requireApiVersion(String apiVer, String apiDevContact) {
try {
if (TextUtils.isEmpty(apiDevContact)) {
return false;
}
Version mVersionCurrent = Version.valueOf(sCurrentJsApiVersion);
Version mVersionSupplied = Version.valueOf(apiVer);
/*
* if api major version equals to supplied major version then return true and also check for minor version and patch version
* show toast for update and contact developer if need updates
* otherwise return false
*/
if (mVersionSupplied.equals(mVersionCurrent)) {
return true;
} else if (mVersionSupplied.lessThan(mVersionCurrent)) {
UIUtils.showThemedToast(AbstractFlashcardViewer.this, getString(R.string.update_js_api_version, mCardSuppliedDeveloperContact), false);
if (mVersionSupplied.greaterThanOrEqualTo(Version.valueOf(sMinimumJsApiVersion))) {
return true;
} else {
return false;
}
} else {
UIUtils.showThemedToast(AbstractFlashcardViewer.this, getString(R.string.valid_js_api_version, mCardSuppliedDeveloperContact), false);
return false;
}
} catch (Exception e) {
Timber.w(e, "requireApiVersion::exception");
}
return false;
}
use of com.ichi2.anki.CardBrowser.Column.CARD 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);
}
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class AbstractFlashcardViewer method showTagsDialog.
protected void showTagsDialog() {
ArrayList<String> tags = new ArrayList<>(getCol().getTags().all());
ArrayList<String> selTags = new ArrayList<>(mCurrentCard.note().getTags());
TagsDialog.TagsDialogListener tagsDialogListener = (selectedTags, option) -> {
if (!mCurrentCard.note().getTags().equals(selectedTags)) {
String tagString = TextUtils.join(" ", selectedTags);
Note note = mCurrentCard.note();
note.setTagsFromStr(tagString);
note.flush();
// Reload current card to reflect tag changes
displayCardQuestion(true);
}
};
TagsDialog dialog = TagsDialog.newInstance(TagsDialog.TYPE_ADD_TAG, selTags, tags);
dialog.setTagsDialogListener(tagsDialogListener);
showDialogFragment(dialog);
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class AbstractFlashcardViewer method answerCard.
protected void answerCard(@Consts.BUTTON_TYPE int ease) {
if (mInAnswer) {
return;
}
mIsSelecting = false;
hideLookupButton();
int buttonNumber = getCol().getSched().answerButtons(mCurrentCard);
// Detect invalid ease for current card (e.g. by using keyboard shortcut or gesture).
if (buttonNumber < ease) {
return;
}
// Set the dots appearing below the toolbar
switch(ease) {
case EASE_1:
mChosenAnswer.setText("\u2022");
mChosenAnswer.setTextColor(ContextCompat.getColor(this, R.color.material_red_500));
break;
case EASE_2:
mChosenAnswer.setText("\u2022\u2022");
mChosenAnswer.setTextColor(ContextCompat.getColor(this, buttonNumber == Consts.BUTTON_FOUR ? R.color.material_blue_grey_600 : R.color.material_green_500));
break;
case EASE_3:
mChosenAnswer.setText("\u2022\u2022\u2022");
mChosenAnswer.setTextColor(ContextCompat.getColor(this, buttonNumber == Consts.BUTTON_FOUR ? R.color.material_green_500 : R.color.material_light_blue_500));
break;
case EASE_4:
mChosenAnswer.setText("\u2022\u2022\u2022\u2022");
mChosenAnswer.setTextColor(ContextCompat.getColor(this, R.color.material_light_blue_500));
break;
default:
Timber.w("Unknown easy type %s", ease);
break;
}
// remove chosen answer hint after a while
mTimerHandler.removeCallbacks(removeChosenAnswerText);
mTimerHandler.postDelayed(removeChosenAnswerText, mShowChosenAnswerLength);
mSoundPlayer.stopSounds();
stopOnlineSpeaking();
mCurrentEase = ease;
CollectionTask.launchCollectionTask(ANSWER_CARD, mAnswerCardHandler(true), new TaskData(mCurrentCard, mCurrentEase));
}
Aggregations