package com.ichi2.anki.dialogs; import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; import android.os.Message; import com.ichi2.anki.AnkiActivity; import com.ichi2.anki.AnkiDroidApp; import com.ichi2.anki.CollectionHelper; import com.ichi2.anki.DeckPicker; import com.ichi2.anki.R; import com.ichi2.async.Connection; import com.ichi2.libanki.Utils; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import timber.log.Timber; /** * We're not allowed to commit fragment transactions from Loader.onLoadCompleted(), * and it's unsafe to commit them from an AsyncTask onComplete event, so we work * around this by using a message handler. */ public class DialogHandler extends Handler { public static final long INTENT_SYNC_MIN_INTERVAL = 2*60000; // 2min minimum sync interval /** * Handler messages */ public static final int MSG_SHOW_COLLECTION_LOADING_ERROR_DIALOG = 0; public static final int MSG_SHOW_COLLECTION_IMPORT_REPLACE_DIALOG = 1; public static final int MSG_SHOW_COLLECTION_IMPORT_ADD_DIALOG = 2; public static final int MSG_SHOW_SYNC_ERROR_DIALOG = 3; public static final int MSG_SHOW_EXPORT_COMPLETE_DIALOG = 4; public static final int MSG_SHOW_MEDIA_CHECK_COMPLETE_DIALOG = 5; public static final int MSG_SHOW_DATABASE_ERROR_DIALOG = 6; public static final int MSG_SHOW_FORCE_FULL_SYNC_DIALOG = 7; public static final int MSG_DO_SYNC = 8; WeakReference<AnkiActivity> mActivity; private static Message sStoredMessage; public DialogHandler(AnkiActivity activity) { // Use weak reference to main activity to prevent leaking the activity when it's closed mActivity = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { Bundle msgData = msg.getData(); if (msg.what == MSG_SHOW_COLLECTION_LOADING_ERROR_DIALOG) { // Collection could not be opened ((DeckPicker) mActivity.get()).showDatabaseErrorDialog(DatabaseErrorDialog.DIALOG_LOAD_FAILED); } else if (msg.what == MSG_SHOW_COLLECTION_IMPORT_REPLACE_DIALOG) { // Handle import of collection package APKG ((DeckPicker) mActivity.get()).showImportDialog(ImportDialog.DIALOG_IMPORT_REPLACE_CONFIRM, msgData.getString("importPath")); } else if (msg.what == MSG_SHOW_COLLECTION_IMPORT_ADD_DIALOG) { // Handle import of deck package APKG ((DeckPicker) mActivity.get()).showImportDialog(ImportDialog.DIALOG_IMPORT_ADD_CONFIRM, msgData.getString("importPath")); } else if (msg.what == MSG_SHOW_SYNC_ERROR_DIALOG) { int id = msgData.getInt("dialogType"); String message = msgData.getString("dialogMessage"); ((DeckPicker) mActivity.get()).showSyncErrorDialog(id, message); } else if (msg.what == MSG_SHOW_EXPORT_COMPLETE_DIALOG) { // Export complete AsyncDialogFragment f = DeckPickerExportCompleteDialog.newInstance(msgData.getString("exportPath")); mActivity.get().showAsyncDialogFragment(f); } else if (msg.what == MSG_SHOW_MEDIA_CHECK_COMPLETE_DIALOG) { // Media check results int id = msgData.getInt("dialogType"); if (id!=MediaCheckDialog.DIALOG_CONFIRM_MEDIA_CHECK) { List<List<String>> checkList = new ArrayList<>(); checkList.add(msgData.getStringArrayList("nohave")); checkList.add(msgData.getStringArrayList("unused")); checkList.add(msgData.getStringArrayList("invalid")); ((DeckPicker) mActivity.get()).showMediaCheckDialog(id, checkList); } } else if (msg.what == MSG_SHOW_DATABASE_ERROR_DIALOG) { // Database error dialog ((DeckPicker) mActivity.get()).showDatabaseErrorDialog(msgData.getInt("dialogType")); } else if (msg.what == MSG_SHOW_FORCE_FULL_SYNC_DIALOG) { // Confirmation dialog for forcing full sync ConfirmationDialog dialog = new ConfirmationDialog (); Runnable confirm = new Runnable() { @Override public void run() { // Bypass the check once the user confirms CollectionHelper.getInstance().getCol(AnkiDroidApp.getInstance()).modSchemaNoCheck(); } }; dialog.setConfirm(confirm); dialog.setArgs(msgData.getString("message")); (mActivity.get()).showDialogFragment(dialog); } else if (msg.what == MSG_DO_SYNC) { SharedPreferences preferences = AnkiDroidApp.getSharedPrefs(mActivity.get()); Resources res = mActivity.get().getResources(); String hkey = preferences.getString("hkey", ""); boolean limited = Utils.intNow(1000) - preferences.getLong("lastSyncTime", 0) < INTENT_SYNC_MIN_INTERVAL; if (!limited && hkey.length() > 0 && Connection.isOnline()) { ((DeckPicker) mActivity.get()).sync(); } else { String err = res.getString(R.string.sync_error); if (limited) { mActivity.get().showSimpleNotification(err, res.getString(R.string.sync_too_busy)); } else { mActivity.get().showSimpleNotification(err, res.getString(R.string.youre_offline)); } } mActivity.get().finishWithoutAnimation(); } } /** * Store a persistent message to static variable * @param message Message to store */ public static void storeMessage(Message message) { Timber.d("Storing persistent message"); sStoredMessage = message; } /** * Read and handle Message which was stored via storeMessage() */ public void readMessage() { Timber.d("Reading persistent message"); if (sStoredMessage != null) { sendMessage(sStoredMessage); } sStoredMessage = null; } }