package com.ichi2.anki.dialogs;
import android.os.Bundle;
import android.os.Message;
import com.afollestad.materialdialogs.MaterialDialog;
import com.ichi2.anki.R;
import com.ichi2.libanki.Collection;
public class SyncErrorDialog extends AsyncDialogFragment {
public static final int DIALOG_USER_NOT_LOGGED_IN_SYNC = 0;
public static final int DIALOG_CONNECTION_ERROR = 1;
public static final int DIALOG_SYNC_CONFLICT_RESOLUTION = 2;
public static final int DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL = 3;
public static final int DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE = 4;
public static final int DIALOG_SYNC_SANITY_ERROR = 6;
public static final int DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL = 7;
public static final int DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE = 8;
public static final int DIALOG_MEDIA_SYNC_ERROR = 9;
public interface SyncErrorDialogListener {
public void showSyncErrorDialog(int dialogType);
public void showSyncErrorDialog(int dialogType, String message);
public void loginToSyncServer();
public void sync();
public void sync(String conflict);
public Collection getCol();
public void mediaCheck();
public void dismissAllDialogFragments();
}
/**
* A set of dialogs belonging to AnkiActivity which deal with sync problems
*
* @param dialogType An integer which specifies which of the sub-dialogs to show
* @param dialogMessage A string which can be optionally used to set the dialog message
*/
public static SyncErrorDialog newInstance(int dialogType, String dialogMessage) {
SyncErrorDialog f = new SyncErrorDialog();
Bundle args = new Bundle();
args.putInt("dialogType", dialogType);
args.putString("dialogMessage", dialogMessage);
f.setArguments(args);
return f;
}
@Override
public MaterialDialog onCreateDialog(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MaterialDialog.Builder builder = new MaterialDialog.Builder(getActivity())
.title(getTitle())
.content(getMessage())
.cancelable(true);
switch (getArguments().getInt("dialogType")) {
case DIALOG_USER_NOT_LOGGED_IN_SYNC:
// User not logged in; take them to login screen
return builder.iconAttr(R.attr.dialogSyncErrorIcon)
.positiveText(res().getString(R.string.log_in))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity()).loginToSyncServer();
}
})
.show();
case DIALOG_CONNECTION_ERROR:
// Connection error; allow user to retry or cancel
return builder.iconAttr(R.attr.dialogSyncErrorIcon)
.positiveText(res().getString(R.string.retry))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity()).sync();
dismissAllDialogFragments();
}
@Override
public void onNegative(MaterialDialog dialog) {
dismissAllDialogFragments();
}
})
.show();
case DIALOG_SYNC_CONFLICT_RESOLUTION:
// Sync conflict; allow user to cancel, or choose between local and remote versions
return builder.iconAttr(R.attr.dialogSyncErrorIcon)
.positiveText(res().getString(R.string.sync_conflict_local))
.negativeText(res().getString(R.string.sync_conflict_remote))
.neutralText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity())
.showSyncErrorDialog(DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL);
}
@Override
public void onNegative(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity())
.showSyncErrorDialog(DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE);
}
@Override
public void onNeutral(MaterialDialog dialog) {
dismissAllDialogFragments();
}
})
.show();
case DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL:
// Confirmation before pushing local collection to server after sync conflict
return builder.positiveText(res().getString(R.string.dialog_positive_overwrite))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
SyncErrorDialogListener activity = (SyncErrorDialogListener) getActivity();
activity.sync("upload");
dismissAllDialogFragments();
}
})
.show();
case DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE:
// Confirmation before overwriting local collection with server collection after sync conflict
return builder.positiveText(res().getString(R.string.dialog_positive_overwrite))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
SyncErrorDialogListener activity = (SyncErrorDialogListener) getActivity();
activity.sync("download");
dismissAllDialogFragments();
}
})
.show();
case DIALOG_SYNC_SANITY_ERROR:
// Sync sanity check error; allow user to cancel, or choose between local and remote versions
return builder.positiveText(res().getString(R.string.sync_sanity_local))
.neutralText(res().getString(R.string.sync_sanity_remote))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity())
.showSyncErrorDialog(DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL);
}
@Override
public void onNeutral(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity())
.showSyncErrorDialog(DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE);
}
})
.show();
case DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL:
// Confirmation before pushing local collection to server after sanity check error
return builder.positiveText(res().getString(R.string.dialog_positive_overwrite))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity()).sync("upload");
dismissAllDialogFragments();
}
})
.show();
case DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE:
// Confirmation before overwriting local collection with server collection after sanity check error
return builder.positiveText(res().getString(R.string.dialog_positive_overwrite))
.negativeText(res().getString(R.string.dialog_cancel))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity()).sync("download");
dismissAllDialogFragments();
}
})
.show();
case DIALOG_MEDIA_SYNC_ERROR:
return builder.positiveText(R.string.check_media)
.negativeText(R.string.cancel)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
((SyncErrorDialogListener) getActivity()).mediaCheck();
dismissAllDialogFragments();
}
})
.show();
default:
return null;
}
}
private String getTitle() {
switch (getArguments().getInt("dialogType")) {
case DIALOG_USER_NOT_LOGGED_IN_SYNC:
return res().getString(R.string.not_logged_in_title);
case DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL:
case DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE:
case DIALOG_SYNC_CONFLICT_RESOLUTION:
return res().getString(R.string.sync_conflict_title);
default:
return res().getString(R.string.sync_error);
}
}
/**
* Get the title which is shown in notification bar when dialog fragment can't be shown
*
* @return tile to be shown in notification in bar
*/
@Override
public String getNotificationTitle() {
switch (getArguments().getInt("dialogType")) {
case DIALOG_USER_NOT_LOGGED_IN_SYNC:
return res().getString(R.string.sync_error);
default:
return getTitle();
}
}
private String getMessage() {
switch (getArguments().getInt("dialogType")) {
case DIALOG_USER_NOT_LOGGED_IN_SYNC:
return res().getString(R.string.login_create_account_message);
case DIALOG_CONNECTION_ERROR:
return res().getString(R.string.connection_error_message);
case DIALOG_SYNC_CONFLICT_RESOLUTION:
return res().getString(R.string.sync_conflict_message);
case DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL:
return res().getString(R.string.sync_conflict_local_confirm);
case DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE:
return res().getString(R.string.sync_conflict_remote_confirm);
case DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL:
return res().getString(R.string.sync_conflict_local_confirm);
case DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE:
return res().getString(R.string.sync_conflict_remote_confirm);
default:
return getArguments().getString("dialogMessage");
}
}
/**
* Get the message which is shown in notification bar when dialog fragment can't be shown
*
* @return message to be shown in notification in bar
*/
@Override
public String getNotificationMessage() {
switch (getArguments().getInt("dialogType")) {
case DIALOG_USER_NOT_LOGGED_IN_SYNC:
return res().getString(R.string.not_logged_in_title);
default:
return getMessage();
}
}
@Override
public Message getDialogHandlerMessage() {
Message msg = Message.obtain();
msg.what = DialogHandler.MSG_SHOW_SYNC_ERROR_DIALOG;
Bundle b = new Bundle();
b.putInt("dialogType", getArguments().getInt("dialogType"));
b.putString("dialogMessage", getArguments().getString("dialogMessage"));
msg.setData(b);
return msg;
}
public void dismissAllDialogFragments() {
((SyncErrorDialogListener) getActivity()).dismissAllDialogFragments();
}
}