use of com.ichi2.utils.FunctionalInterfaces.Function in project Anki-Android by ankidroid.
the class AudioPlayerTest method testStopWithIOException.
// tests if the stop() function successfully catches an IOException
@Test
public void testStopWithIOException() {
ShadowMediaPlayer.addException(DataSource.toDataSource(mFile.getAbsolutePath()), new IOException("Expected"));
assertDoesNotThrow(() -> {
mAudioPlayer.stop();
});
}
use of com.ichi2.utils.FunctionalInterfaces.Function in project Anki-Android by Ramblurr.
the class BasicTextFieldController method createCloneButton.
/**
* @param activity
* @param layoutTools This creates a button, which will call a dialog, allowing to pick from another note's fields
* one, and use it's value in the current one.
* @param p
*/
private void createCloneButton(LinearLayout layoutTools, LayoutParams p) {
// Makes sense only for two and more fields
if (mNote.getNumberOfFields() > 1) {
// Should be more than one text not empty fields for clone to make
// sense
mPossibleClones = new ArrayList<String>();
int numTextFields = 0;
for (int i = 0; i < mNote.getNumberOfFields(); ++i) {
// Sort out non text and empty fields
IField curField = mNote.getField(i);
if (curField == null) {
continue;
}
if (curField.getType() != EFieldType.TEXT) {
continue;
}
if (curField.getText() == null) {
continue;
}
if (curField.getText().length() == 0) {
continue;
}
// as well as the same field
if (curField.getText().contentEquals(mField.getText())) {
continue;
}
// collect clone sources
mPossibleClones.add(curField.getText());
++numTextFields;
}
// Nothing to clone from
if (numTextFields < 1) {
return;
}
Button btnOtherField = new Button(mActivity);
btnOtherField.setText(gtxt(R.string.multimedia_editor_text_field_editing_clone));
layoutTools.addView(btnOtherField, p);
final BasicTextFieldController controller = this;
btnOtherField.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
PickStringDialogFragment fragment = new PickStringDialogFragment();
fragment.setChoices(mPossibleClones);
fragment.setOnclickListener(controller);
fragment.setTitle(gtxt(R.string.multimedia_editor_text_field_editing_clone_source));
fragment.show(mActivity.getSupportFragmentManager(), "pick.clone");
// flow continues in the onClick function
}
});
}
}
use of com.ichi2.utils.FunctionalInterfaces.Function in project AnkiChinaAndroid by ankichinateam.
the class Collection method fixIntegrity.
/**
* Fix possible problems and rebuild caches.
*/
public CheckDatabaseResult fixIntegrity(CollectionTask.ProgressCallback progressCallback) {
File file = new File(mPath);
CheckDatabaseResult result = new CheckDatabaseResult(file.length());
final int[] currentTask = { 1 };
// a few fixes are in all-models loops, the rest are one-offs
int totalTasks = (getModels().all().size() * 4) + 27;
Runnable notifyProgress = progressCallback == null ? null : () -> fixIntegrityProgress(progressCallback, currentTask[0]++, totalTasks);
FunctionalInterfaces.Consumer<FunctionalInterfaces.FunctionThrowable<Runnable, List<String>, JSONException>> executeIntegrityTask = (FunctionalInterfaces.FunctionThrowable<Runnable, List<String>, JSONException> function) -> {
// DEFECT: notifyProgress will lag if an exception is thrown.
try {
mDb.getDatabase().beginTransaction();
if (notifyProgress != null)
result.addAll(function.apply(notifyProgress));
mDb.getDatabase().setTransactionSuccessful();
} catch (Exception e) {
Timber.e(e, "Failed to execute integrity check");
AnkiDroidApp.sendExceptionReport(e, "fixIntegrity");
} finally {
try {
mDb.getDatabase().endTransaction();
} catch (Exception e) {
Timber.e(e, "Failed to end integrity check transaction");
AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - endTransaction");
}
}
};
try {
mDb.getDatabase().beginTransaction();
save();
notifyProgress.run();
if (!mDb.getDatabase().isDatabaseIntegrityOk()) {
return result.markAsFailed();
}
mDb.getDatabase().setTransactionSuccessful();
} catch (SQLiteDatabaseLockedException ex) {
Timber.e("doInBackgroundCheckDatabase - Database locked");
return result.markAsLocked();
} catch (RuntimeException e) {
Timber.e(e, "doInBackgroundCheckDatabase - RuntimeException on marking card");
AnkiDroidApp.sendExceptionReport(e, "doInBackgroundCheckDatabase");
return result.markAsFailed();
} finally {
// if the database was locked, we never got the transaction.
if (mDb.getDatabase().inTransaction()) {
mDb.getDatabase().endTransaction();
}
}
executeIntegrityTask.consume(this::deleteNotesWithMissingModel);
// for each model
for (JSONObject m : getModels().all()) {
executeIntegrityTask.consume((callback) -> deleteCardsWithInvalidModelOrdinals(callback, m));
executeIntegrityTask.consume((callback) -> deleteNotesWithWrongFieldCounts(callback, m));
}
executeIntegrityTask.consume(this::deleteNotesWithMissingCards);
executeIntegrityTask.consume(this::deleteCardsWithMissingNotes);
executeIntegrityTask.consume(this::removeOriginalDuePropertyWhereInvalid);
executeIntegrityTask.consume(this::removeDynamicPropertyFromNonDynamicDecks);
executeIntegrityTask.consume(this::removeDeckOptionsFromDynamicDecks);
executeIntegrityTask.consume(this::resetInvalidDeckOptions);
executeIntegrityTask.consume(this::rebuildTags);
executeIntegrityTask.consume(this::updateFieldCache);
executeIntegrityTask.consume(this::fixNewCardDuePositionOverflow);
executeIntegrityTask.consume(this::resetNewCardInsertionPosition);
executeIntegrityTask.consume(this::fixExcessiveReviewDueDates);
// v2 sched had a bug that could create decimal intervals
executeIntegrityTask.consume(this::fixDecimalCardsData);
executeIntegrityTask.consume(this::fixDecimalRevLogData);
executeIntegrityTask.consume(this::restoreMissingDatabaseIndices);
executeIntegrityTask.consume(this::ensureModelsAreNotEmpty);
executeIntegrityTask.consume((progressNotifier) -> this.ensureCardsHaveHomeDeck(progressNotifier, result));
// and finally, optimize (unable to be done inside transaction).
try {
optimize(notifyProgress);
} catch (Exception e) {
Timber.e(e, "optimize");
AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - optimize");
}
file = new File(mPath);
long newSize = file.length();
result.setNewSize(newSize);
// if any problems were found, force a full sync
if (result.hasProblems()) {
modSchemaNoCheck();
}
logProblems(result.getProblems());
return result;
}
use of com.ichi2.utils.FunctionalInterfaces.Function in project Anki-Android by ankidroid.
the class SchedV2 method _updateCutoff.
/**
* Daily cutoff ************************************************************* **********************************
* This function uses GregorianCalendar so as to be sensitive to leap years, daylight savings, etc.
*/
/* Overriden: other way to count time*/
@RustCleanup("remove timing == null check once JavaBackend is removed")
public void _updateCutoff() {
int oldToday = mToday == null ? 0 : mToday;
SchedTimingToday timing = _timingToday();
if (timing == null) {
mToday = _daysSinceCreation();
mDayCutoff = _dayCutoff();
} else if (_new_timezone_enabled()) {
mToday = timing.days_elapsed();
mDayCutoff = timing.next_day_at();
} else {
mToday = _daysSinceCreation();
mDayCutoff = _dayCutoff();
}
if (oldToday != mToday) {
mCol.log(mToday, mDayCutoff);
}
// instead
for (Deck deck : mCol.getDecks().all()) {
update(deck);
}
// unbury if the day has rolled over
int unburied = mCol.get_config("lastUnburied", 0);
if (unburied < mToday) {
SyncStatus.ignoreDatabaseModification(this::unburyCards);
mCol.set_config("lastUnburied", mToday);
}
}
use of com.ichi2.utils.FunctionalInterfaces.Function in project Anki-Android by ankidroid.
the class Collection method fixIntegrity.
/**
* Fix possible problems and rebuild caches.
*/
public CheckDatabaseResult fixIntegrity(TaskManager.ProgressCallback<String> progressCallback) {
File file = new File(mPath);
CheckDatabaseResult result = new CheckDatabaseResult(file.length());
final int[] currentTask = { 1 };
// a few fixes are in all-models loops, the rest are one-offs
int totalTasks = (getModels().all().size() * 4) + 27;
Runnable notifyProgress = () -> fixIntegrityProgress(progressCallback, currentTask[0]++, totalTasks);
Consumer<FunctionalInterfaces.FunctionThrowable<Runnable, List<String>, JSONException>> executeIntegrityTask = function -> {
// DEFECT: notifyProgress will lag if an exception is thrown.
try {
mDb.getDatabase().beginTransaction();
result.addAll(function.apply(notifyProgress));
mDb.getDatabase().setTransactionSuccessful();
} catch (Exception e) {
Timber.e(e, "Failed to execute integrity check");
AnkiDroidApp.sendExceptionReport(e, "fixIntegrity");
} finally {
try {
mDb.getDatabase().endTransaction();
} catch (Exception e) {
Timber.e(e, "Failed to end integrity check transaction");
AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - endTransaction");
}
}
};
try {
mDb.getDatabase().beginTransaction();
save();
notifyProgress.run();
if (!mDb.getDatabase().isDatabaseIntegrityOk()) {
return result.markAsFailed();
}
mDb.getDatabase().setTransactionSuccessful();
} catch (SQLiteDatabaseLockedException ex) {
Timber.w(ex, "doInBackgroundCheckDatabase - Database locked");
return result.markAsLocked();
} catch (RuntimeException e) {
Timber.e(e, "doInBackgroundCheckDatabase - RuntimeException on marking card");
AnkiDroidApp.sendExceptionReport(e, "doInBackgroundCheckDatabase");
return result.markAsFailed();
} finally {
// if the database was locked, we never got the transaction.
if (mDb.getDatabase().inTransaction()) {
mDb.getDatabase().endTransaction();
}
}
executeIntegrityTask.accept(this::deleteNotesWithMissingModel);
// for each model
for (Model m : getModels().all()) {
executeIntegrityTask.accept((callback) -> deleteCardsWithInvalidModelOrdinals(callback, m));
executeIntegrityTask.accept((callback) -> deleteNotesWithWrongFieldCounts(callback, m));
}
executeIntegrityTask.accept(this::deleteNotesWithMissingCards);
executeIntegrityTask.accept(this::deleteCardsWithMissingNotes);
executeIntegrityTask.accept(this::removeOriginalDuePropertyWhereInvalid);
executeIntegrityTask.accept(this::removeDynamicPropertyFromNonDynamicDecks);
executeIntegrityTask.accept(this::removeDeckOptionsFromDynamicDecks);
executeIntegrityTask.accept(this::resetInvalidDeckOptions);
executeIntegrityTask.accept(this::rebuildTags);
executeIntegrityTask.accept(this::updateFieldCache);
executeIntegrityTask.accept(this::fixNewCardDuePositionOverflow);
executeIntegrityTask.accept(this::resetNewCardInsertionPosition);
executeIntegrityTask.accept(this::fixExcessiveReviewDueDates);
// v2 sched had a bug that could create decimal intervals
executeIntegrityTask.accept(this::fixDecimalCardsData);
executeIntegrityTask.accept(this::fixDecimalRevLogData);
executeIntegrityTask.accept(this::restoreMissingDatabaseIndices);
executeIntegrityTask.accept(this::ensureModelsAreNotEmpty);
executeIntegrityTask.accept((progressNotifier) -> this.ensureCardsHaveHomeDeck(progressNotifier, result));
// and finally, optimize (unable to be done inside transaction).
try {
optimize(notifyProgress);
} catch (Exception e) {
Timber.e(e, "optimize");
AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - optimize");
}
file = new File(mPath);
long newSize = file.length();
result.setNewSize(newSize);
// if any problems were found, force a full sync
if (result.hasProblems()) {
modSchemaNoCheck();
}
logProblems(result.getProblems());
return result;
}
Aggregations