/***************************************************************************************
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 3 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
package com.ichi2.widget;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Pair;
import com.ichi2.anki.AnkiDroidApp;
import com.ichi2.anki.CollectionHelper;
import com.ichi2.anki.MetaDB;
import com.ichi2.anki.services.NotificationService;
import com.ichi2.async.BaseAsyncTask;
import com.ichi2.libanki.Collection;
import com.ichi2.libanki.Sched;
import java.util.List;
import timber.log.Timber;
/**
* The status of the widget.
*/
public final class WidgetStatus {
private static boolean sSmallWidgetEnabled = false;
private static boolean sNotificationEnabled = false;
private static AsyncTask<Context, Void, Context> sUpdateDeckStatusAsyncTask;
/** This class should not be instantiated. */
private WidgetStatus() {
}
/**
* Request the widget to update its status.
*/
public static void update(Context context) {
SharedPreferences preferences = AnkiDroidApp.getSharedPrefs(context);
sSmallWidgetEnabled = preferences.getBoolean("widgetSmallEnabled", false);
sNotificationEnabled = Integer.parseInt(preferences.getString("minimumCardsDueForNotification", "1000001")) < 1000000;
if ((sSmallWidgetEnabled || sNotificationEnabled)
&& ((sUpdateDeckStatusAsyncTask == null) || (sUpdateDeckStatusAsyncTask.getStatus() == AsyncTask.Status.FINISHED))) {
Timber.d("WidgetStatus.update(): updating");
sUpdateDeckStatusAsyncTask = new UpdateDeckStatusAsyncTask();
sUpdateDeckStatusAsyncTask.execute(context);
} else {
Timber.d("WidgetStatus.update(): already running or not enabled");
}
}
/** Returns the status of each of the decks. */
public static int[] fetchSmall(Context context) {
return MetaDB.getWidgetSmallStatus(context);
}
public static int fetchDue(Context context) {
return MetaDB.getNotificationStatus(context);
}
private static class UpdateDeckStatusAsyncTask extends BaseAsyncTask<Context, Void, Context> {
// due, eta
private static Pair<Integer, Integer> sSmallWidgetStatus = new Pair<>(0, 0);
@Override
protected Context doInBackground(Context... params) {
super.doInBackground(params);
Timber.d("WidgetStatus.UpdateDeckStatusAsyncTask.doInBackground()");
Context context = params[0];
if (!AnkiDroidApp.isSdCardMounted()) {
return context;
}
try {
updateCounts(context);
} catch (Exception e) {
Timber.e(e, "Could not update widget");
}
return context;
}
@Override
protected void onPostExecute(Context context) {
super.onPostExecute(context);
Timber.d("WidgetStatus.UpdateDeckStatusAsyncTask.onPostExecute()");
MetaDB.storeSmallWidgetStatus(context, sSmallWidgetStatus);
if (sSmallWidgetEnabled) {
Intent intent;
intent = new Intent(context, AnkiDroidWidgetSmall.UpdateService.class);
context.startService(intent);
}
if (sNotificationEnabled) {
Intent intent;
intent = new Intent(context, NotificationService.class);
context.startService(intent);
}
}
private void updateCounts(Context context) {
int[] total = {0, 0, 0};
Collection col = CollectionHelper.getInstance().getCol(context);
// Ensure queues are reset if we cross over to the next day.
col.getSched()._checkDay();
// Only count the top-level decks in the total
List<Sched.DeckDueTreeNode> nodes = col.getSched().deckDueTree();
for (Sched.DeckDueTreeNode node : nodes) {
total[0] += node.newCount;
total[1] += node.lrnCount;
total[2] += node.revCount;
}
int due = total[0] + total[1] + total[2];
int eta = col.getSched().eta(total, false);
sSmallWidgetStatus = new Pair<>(due, eta);
}
}
}