use of com.ichi2.utils.JSONException in project AnkiChinaAndroid by ankichinateam.
the class Statistics method selectDropDownItem.
private void selectDropDownItem(int position) {
mActionBarSpinner.setSelection(position);
if (position == 0) {
mDeckId = Stats.ALL_DECKS_ID;
} else {
Deck deck = mDropDownDecks.get(position - 1);
try {
mDeckId = deck.getLong("id");
} catch (JSONException e) {
Timber.e(e, "Could not get ID from deck");
}
}
mTaskHandler.setDeckId(mDeckId);
mViewPager.getAdapter().notifyDataSetChanged();
}
use of com.ichi2.utils.JSONException in project AnkiChinaAndroid by ankichinateam.
the class DeckOptions method onCreate.
@Override
// conversion to fragments tracked as #5019 in github
@SuppressWarnings("deprecation")
protected void onCreate(Bundle icicle) {
Themes.setThemeLegacy(this);
super.onCreate(icicle);
mCol = CollectionHelper.getInstance().getCol(this);
if (mCol == null) {
finish();
return;
}
Bundle extras = getIntent().getExtras();
if (extras != null && extras.containsKey("did")) {
mDeck = mCol.getDecks().get(extras.getLong("did"));
} else {
mDeck = mCol.getDecks().current();
}
registerExternalStorageListener();
if (mCol == null) {
Timber.w("DeckOptions - No Collection loaded");
finish();
} else {
mPref = new DeckPreferenceHack();
// #6068 - constructor can call finish()
if (this.isFinishing()) {
return;
}
mPref.registerOnSharedPreferenceChangeListener(this);
this.addPreferencesFromResource(R.xml.deck_options);
this.buildLists();
this.updateSummaries();
// Set the activity title to include the name of the deck
String title = getResources().getString(R.string.deckpreferences_title);
if (title.contains("XXX")) {
try {
title = title.replace("XXX", mDeck.getString("name"));
} catch (JSONException e) {
title = title.replace("XXX", "???");
}
}
this.setTitle(title);
}
// Add a home button to the actionbar
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
use of com.ichi2.utils.JSONException in project AnkiChinaAndroid by ankichinateam.
the class DeckPicker method showStartupScreensAndDialogs.
public void showStartupScreensAndDialogs(SharedPreferences preferences, int skip) {
if (!BackupManager.enoughDiscSpace(CollectionHelper.getCurrentAnkiDroidDirectory(this))) {
Timber.i("Not enough space to do backup");
showDialogFragment(DeckPickerNoSpaceLeftDialog.newInstance());
} else if (preferences.getBoolean("noSpaceLeft", false)) {
Timber.i("No space left");
showDialogFragment(DeckPickerBackupNoSpaceLeftDialog.newInstance());
preferences.edit().remove("noSpaceLeft").apply();
} else if ("".equals(preferences.getString("lastVersion", ""))) {
Timber.i("Fresh install");
preferences.edit().putString("lastVersion", VersionUtils.getPkgVersionName()).apply();
onFinishedStartup();
} else if (skip < 2 && !preferences.getString("lastVersion", "").equals(VersionUtils.getPkgVersionName())) {
Timber.i("AnkiDroid is being updated and a collection already exists.");
// The user might appreciate us now, see if they will help us get better?
if (!preferences.contains(UsageAnalytics.ANALYTICS_OPTIN_KEY)) {
showDialogFragment(DeckPickerAnalyticsOptInDialog.newInstance());
}
// For upgrades, we check if we are upgrading
// to a version that contains additions to the database integrity check routine that we would
// like to run on all collections. A missing version number is assumed to be a fresh
// installation of AnkiDroid and we don't run the check.
long current = VersionUtils.getPkgVersionCode();
Timber.i("Current AnkiDroid version: %s", current);
long previous;
if (preferences.contains(UPGRADE_VERSION_KEY)) {
// Upgrading currently installed app
previous = getPreviousVersion(preferences, current);
} else {
// Fresh install
previous = current;
}
preferences.edit().putLong(UPGRADE_VERSION_KEY, current).apply();
// It is rebuilt on the next sync or media check
if (previous < 20300200) {
Timber.i("Deleting media database");
File mediaDb = new File(CollectionHelper.getCurrentAnkiDroidDirectory(this), "collection.media.ad.db2");
if (mediaDb.exists()) {
mediaDb.delete();
}
}
// Recommend the user to do a full-sync if they're upgrading from before 2.3.1beta8
if (previous < 20301208) {
Timber.i("Recommend the user to do a full-sync");
mRecommendFullSync = true;
}
// Fix "font-family" definition in templates created by AnkiDroid before 2.6alhpa23
if (previous < 20600123) {
Timber.i("Fixing font-family definition in templates");
try {
Models models = getCol().getModels();
for (Model m : models.all()) {
String css = m.getString("css");
if (css.contains("font-familiy")) {
m.put("css", css.replace("font-familiy", "font-family"));
models.save(m);
}
}
models.flush();
} catch (JSONException e) {
Timber.e(e, "Failed to upgrade css definitions.");
}
}
// Check if preference upgrade or database check required, otherwise go to new feature screen
int upgradePrefsVersion = AnkiDroidApp.CHECK_PREFERENCES_AT_VERSION;
int upgradeDbVersion = AnkiDroidApp.CHECK_DB_AT_VERSION;
// Specifying a checkpoint in the future is not supported, please don't do it!
if (current < upgradePrefsVersion) {
Timber.e("Checkpoint in future produced.");
UIUtils.showSimpleSnackbar(this, "Invalid value for CHECK_PREFERENCES_AT_VERSION", false);
onFinishedStartup();
return;
}
if (current < upgradeDbVersion) {
Timber.e("Invalid value for CHECK_DB_AT_VERSION");
UIUtils.showSimpleSnackbar(this, "Invalid value for CHECK_DB_AT_VERSION", false);
onFinishedStartup();
return;
}
// Skip full DB check if the basic check is OK
// TODO: remove this variable if we really want to do the full db check on every user
boolean skipDbCheck = false;
// noinspection ConstantConditions
if ((!skipDbCheck && previous < upgradeDbVersion) || previous < upgradePrefsVersion) {
if (previous < upgradePrefsVersion) {
Timber.i("showStartupScreensAndDialogs() running upgradePreferences()");
upgradePreferences(previous);
}
// noinspection ConstantConditions
if (!skipDbCheck && previous < upgradeDbVersion) {
Timber.i("showStartupScreensAndDialogs() running integrityCheck()");
// #5852 - since we may have a warning about disk space, we don't want to force a check database
// and show a warning before the user knows what is happening.
new MaterialDialog.Builder(this).title(R.string.integrity_check_startup_title).content(R.string.integrity_check_startup_content).positiveText(R.string.integrity_check_positive).negativeText(R.string.close).onPositive((materialDialog, dialogAction) -> integrityCheck()).onNeutral((materialDialog, dialogAction) -> this.restartActivity()).onNegative((materialDialog, dialogAction) -> this.restartActivity()).canceledOnTouchOutside(false).cancelable(false).build().show();
} else if (previous < upgradePrefsVersion) {
Timber.i("Updated preferences with no integrity check - restarting activity");
// If integrityCheck() doesn't occur, but we did update preferences we should restart DeckPicker to
// proceed
this.restartActivity();
}
} else {
// If no changes are required we go to the new features activity
// There the "lastVersion" is set, so that this code is not reached again
// if (VersionUtils.isReleaseVersion()) {
// Timber.i("Displaying new features");
// Intent infoIntent = new Intent(this, Info.class);
// infoIntent.putExtra(Info.TYPE_EXTRA, Info.TYPE_NEW_VERSION);
//
// if (skip != 0) {
// startActivityForResultWithAnimation(infoIntent, SHOW_INFO_NEW_VERSION,
// ActivityTransitionAnimation.LEFT);
// } else {
// startActivityForResultWithoutAnimation(infoIntent, SHOW_INFO_NEW_VERSION);
// }
// } else {
Timber.i("Dev Build - not showing 'new features'");
// Don't show new features dialog for development builds
preferences.edit().putString("lastVersion", VersionUtils.getPkgVersionName()).apply();
String ver = getResources().getString(R.string.updated_version, VersionUtils.getPkgVersionName());
UIUtils.showSnackbar(this, ver, true, -1, null, findViewById(R.id.root_layout), null);
showStartupScreensAndDialogs(preferences, 2);
// }
}
} else {
// this is the main call when there is nothing special required
Timber.i("No startup screens required");
onFinishedStartup();
}
}
use of com.ichi2.utils.JSONException in project AnkiChinaAndroid by ankichinateam.
the class CardBrowser 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.action_add_note_from_card_browser:
{
Intent intent = new Intent(CardBrowser.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_search_by_tag:
showTagsDialog();
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 (mInMultiSelectMode) {
CollectionTask.launchCollectionTask(DISMISS_MULTI, mDeleteNoteHandler, new TaskData(new Object[] { getSelectedCardIds(), Collection.DismissType.DELETE_NOTE_MULTI }));
mCheckedCards.clear();
endMultiSelectMode();
mCardsAdapter.notifyDataSetChanged();
}
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 }));
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), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builderSingle.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int 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_select_none:
onSelectNone();
return true;
case R.id.action_select_all:
onSelectAll();
return true;
case R.id.action_preview:
{
Intent previewer = new Intent(CardBrowser.this, Previewer.class);
if (mInMultiSelectMode && checkedCardCount() > 1) {
// Multiple cards have been explicitly selected, so preview only those cards
previewer.putExtra("index", 0);
previewer.putExtra("cardList", getSelectedCardIds());
} else {
// Preview all cards, starting from the one that is currently selected
int startIndex = mCheckedCards.isEmpty() ? 0 : mCheckedCards.iterator().next().getPosition();
previewer.putExtra("index", startIndex);
previewer.putExtra("cardList", getAllCardIds());
}
startActivityForResultWithoutAnimation(previewer, PREVIEW_CARDS);
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);
}
}
use of com.ichi2.utils.JSONException in project AnkiChinaAndroid by ankichinateam.
the class AbstractFlashcardViewer method restoreCollectionPreferences.
protected void restoreCollectionPreferences() {
// These are preferences we pull out of the collection instead of SharedPreferences
try {
mShowNextReviewTime = getCol().getConf().getBoolean("estTimes");
// Dynamic don't have review options; attempt to get deck-specific auto-advance options
// but be prepared to go with all default if it's a dynamic deck
JSONObject revOptions = new JSONObject();
long selectedDid = getCol().getDecks().selected();
if (!getCol().getDecks().isDyn(selectedDid)) {
revOptions = getCol().getDecks().confForDid(selectedDid).getJSONObject("rev");
}
mOptUseGeneralTimerSettings = revOptions.optBoolean("useGeneralTimeoutSettings", true);
mOptUseTimer = revOptions.optBoolean("timeoutAnswer", false);
mOptWaitAnswerSecond = revOptions.optInt("timeoutAnswerSeconds", 20);
mOptWaitQuestionSecond = revOptions.optInt("timeoutQuestionSeconds", 60);
} catch (JSONException e) {
Timber.e(e, "Unable to restoreCollectionPreferences");
throw new RuntimeException(e);
} catch (NullPointerException npe) {
// NPE on collection only happens if the Collection is broken, follow AnkiActivity example
Intent deckPicker = new Intent(this, DeckPicker.class);
// don't currently do anything with this
deckPicker.putExtra("collectionLoadError", true);
deckPicker.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityWithAnimation(deckPicker, ActivityTransitionAnimation.LEFT);
}
}
Aggregations