package org.wikipedia.readinglist;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.wikipedia.R;
import org.wikipedia.WikipediaApp;
import org.wikipedia.analytics.ReadingListsFunnel;
import org.wikipedia.concurrency.CallbackTask;
import org.wikipedia.model.EnumCode;
import org.wikipedia.model.EnumCodeMap;
import org.wikipedia.page.ExtendedBottomSheetDialogFragment;
import org.wikipedia.page.PageTitle;
import org.wikipedia.readinglist.page.ReadingListPage;
import org.wikipedia.readinglist.page.database.ReadingListDaoProxy;
import org.wikipedia.readinglist.page.database.ReadingListPageDao;
import org.wikipedia.readinglist.sync.ReadingListSynchronizer;
import org.wikipedia.settings.Prefs;
import org.wikipedia.util.DimenUtil;
import org.wikipedia.util.FeedbackUtil;
import java.util.ArrayList;
import java.util.List;
public class AddToReadingListDialog extends ExtendedBottomSheetDialogFragment {
public enum InvokeSource implements EnumCode {
BOOKMARK_BUTTON(0),
CONTEXT_MENU(1),
LINK_PREVIEW_MENU(2),
PAGE_OVERFLOW_MENU(3),
FEED(4),
NEWS_ACTIVITY(5),
READING_LIST_ACTIVITY(6);
private static final EnumCodeMap<InvokeSource> MAP = new EnumCodeMap<>(InvokeSource.class);
private final int code;
public static InvokeSource of(int code) {
return MAP.get(code);
}
@Override public int code() {
return code;
}
InvokeSource(int code) {
this.code = code;
}
}
private PageTitle pageTitle;
private ReadingListAdapter adapter;
private View listsContainer;
private View onboardingContainer;
private View onboardingButton;
private InvokeSource invokeSource;
private CreateButtonClickListener createClickListener = new CreateButtonClickListener();
private ReadingLists readingLists = new ReadingLists();
@Nullable private DialogInterface.OnDismissListener dismissListener;
private ReadingListItemCallback listItemCallback = new ReadingListItemCallback();
public static AddToReadingListDialog newInstance(@NonNull PageTitle title, InvokeSource source) {
return newInstance(title, source, null);
}
public static AddToReadingListDialog newInstance(@NonNull PageTitle title, InvokeSource source,
@Nullable DialogInterface.OnDismissListener listener) {
AddToReadingListDialog dialog = new AddToReadingListDialog();
Bundle args = new Bundle();
args.putParcelable("title", title);
args.putInt("source", source.code());
dialog.setArguments(args);
dialog.setOnDismissListener(listener);
return dialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageTitle = getArguments().getParcelable("title");
invokeSource = InvokeSource.of(getArguments().getInt("source"));
adapter = new ReadingListAdapter();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.dialog_add_to_reading_list, container);
listsContainer = rootView.findViewById(R.id.lists_container);
onboardingContainer = rootView.findViewById(R.id.onboarding_container);
onboardingButton = rootView.findViewById(R.id.onboarding_button);
checkAndShowOnboarding();
RecyclerView readingListView = (RecyclerView) rootView.findViewById(R.id.list_of_lists);
readingListView.setLayoutManager(new LinearLayoutManager(getActivity()));
readingListView.setAdapter(adapter);
View createButton = rootView.findViewById(R.id.create_button);
createButton.setOnClickListener(createClickListener);
if (savedInstanceState == null) {
// Log a click event, but only the first time the dialog is shown.
new ReadingListsFunnel(pageTitle.getWikiSite()).logAddClick(invokeSource);
}
updateLists();
return rootView;
}
@Override
public void onStart() {
super.onStart();
BottomSheetBehavior.from((View) getView().getParent()).setPeekHeight(DimenUtil
.roundedDpToPx(DimenUtil.getDimension(R.dimen.readingListSheetPeekHeight)));
}
@Override
public void dismiss() {
super.dismiss();
if (dismissListener != null) {
dismissListener.onDismiss(null);
}
}
public void setOnDismissListener(DialogInterface.OnDismissListener listener) {
dismissListener = listener;
}
private void checkAndShowOnboarding() {
boolean isOnboarding = WikipediaApp.getInstance().getOnboardingStateMachine().isReadingListTutorialEnabled();
onboardingButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onboardingContainer.setVisibility(View.GONE);
listsContainer.setVisibility(View.VISIBLE);
WikipediaApp.getInstance().getOnboardingStateMachine().setReadingListTutorial();
if (readingLists.isEmpty()) {
showCreateListDialog();
}
}
});
listsContainer.setVisibility(isOnboarding ? View.GONE : View.VISIBLE);
onboardingContainer.setVisibility(isOnboarding ? View.VISIBLE : View.GONE);
}
private void updateLists() {
ReadingList.DAO.queryMruLists(null, new CallbackTask.DefaultCallback<List<ReadingList>>() {
@Override public void success(List<ReadingList> rows) {
readingLists.set(rows);
readingLists.sort(Prefs.getReadingListSortMode(ReadingLists.SORT_BY_NAME_ASC));
adapter.notifyDataSetChanged();
}
});
}
private class CreateButtonClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
showCreateListDialog();
}
}
private void showCreateListDialog() {
String title = getString(R.string.reading_list_name_sample);
long now = System.currentTimeMillis();
final ReadingList list = ReadingList
.builder()
.key(ReadingListDaoProxy.listKey(title))
.title(title)
.mtime(now)
.atime(now)
.description(null)
.pages(new ArrayList<ReadingListPage>())
.build();
ReadingListTitleDialog.readingListTitleDialog(getContext(), list.getTitle(),
readingLists.getTitles(), new ReadingListTitleDialog.Callback() {
@Override
public void onSuccess(@NonNull CharSequence text) {
list.setTitle(text.toString());
ReadingList.DAO.addList(list);
addAndDismiss(list);
}
}).show();
}
private void addAndDismiss(final ReadingList readingList) {
final ReadingListPage page = findOrCreatePage(readingList, pageTitle);
ReadingList.DAO.listContainsTitleAsync(readingList, page, new CallbackTask.DefaultCallback<Boolean>() {
@Override public void success(Boolean contains) {
if (isAdded()) {
String message;
if (contains) {
message = getString(R.string.reading_list_already_exists);
} else {
message = TextUtils.isEmpty(readingList.getTitle())
? getString(R.string.reading_list_added_to_unnamed)
: String.format(getString(R.string.reading_list_added_to_named),
readingList.getTitle());
new ReadingListsFunnel(pageTitle.getWikiSite()).logAddToList(readingList, readingLists.size(), invokeSource);
ReadingList.DAO.makeListMostRecent(readingList);
}
showViewListSnackBar(readingList, message);
ReadingList.DAO.addTitleToList(readingList, page, false);
ReadingListSynchronizer.instance().bumpRevAndSync();
dismiss();
}
}
});
}
private void showViewListSnackBar(@NonNull final ReadingList readingList, @NonNull String message) {
FeedbackUtil.makeSnackbar(getActivity(), message, FeedbackUtil.LENGTH_DEFAULT)
.setAction(R.string.reading_list_added_view_button, new View.OnClickListener() {
@Override
public void onClick(View v) {
v.getContext().startActivity(ReadingListActivity.newIntent(v.getContext(), readingList));
}
}).show();
}
@NonNull private ReadingListPage findOrCreatePage(ReadingList readingList, PageTitle title) {
ReadingListPage page = ReadingListPageDao.instance().findPage(ReadingListDaoProxy.key(title));
if (page == null) {
page = ReadingListDaoProxy.page(readingList, title);
}
return page;
}
private class ReadingListItemCallback implements ReadingListItemView.Callback {
@Override
public void onClick(@NonNull ReadingList readingList) {
addAndDismiss(readingList);
}
@Override
public void onRename(@NonNull final ReadingList readingList) {
}
@Override
public void onEditDescription(@NonNull final ReadingList readingList) {
}
@Override
public void onDelete(@NonNull ReadingList readingList) {
}
}
private class ReadingListItemHolder extends RecyclerView.ViewHolder {
private ReadingListItemView itemView;
ReadingListItemHolder(ReadingListItemView itemView) {
super(itemView);
this.itemView = itemView;
itemView.setOverflowButtonVisible(false);
}
public void bindItem(ReadingList readingList) {
itemView.setReadingList(readingList);
}
public ReadingListItemView getView() {
return itemView;
}
}
private final class ReadingListAdapter extends RecyclerView.Adapter<ReadingListItemHolder> {
@Override
public int getItemCount() {
return readingLists.size();
}
@Override
public ReadingListItemHolder onCreateViewHolder(ViewGroup parent, int pos) {
ReadingListItemView view = new ReadingListItemView(getContext());
return new ReadingListItemHolder(view);
}
@Override
public void onBindViewHolder(ReadingListItemHolder holder, int pos) {
holder.bindItem(readingLists.get(pos));
}
@Override public void onViewAttachedToWindow(ReadingListItemHolder holder) {
super.onViewAttachedToWindow(holder);
holder.getView().setCallback(listItemCallback);
}
@Override public void onViewDetachedFromWindow(ReadingListItemHolder holder) {
holder.getView().setCallback(null);
super.onViewDetachedFromWindow(holder);
}
}
}