blob: 645f357d4f0df2400dc7c5503b3962a4b1524e2f [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.todos;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import io.v.todos.model.ListMetadata;
public final class UIUtil {
private UIUtil() {
}
private static final long JUST_NOW_DURATION = 60 * 1000 - 1;
public static String computeTimeAgo(Context context, String prefix, long startTime) {
long now = System.currentTimeMillis();
return prefix + ": " + (now - startTime > JUST_NOW_DURATION ?
DateUtils.getRelativeTimeSpanString(startTime, now, DateUtils.MINUTE_IN_MILLIS) :
context.getString(R.string.just_now));
}
private static AlertDialog lastDialog;
public static AlertDialog getLastDialog() {
return lastDialog;
}
public static void showAddDialog(Context context, String title,
final DialogResponseListener addListener) {
final EditText todoItem = new EditText(context);
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(title)
.setView(todoItem)
.setPositiveButton("Add", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addListener.handleResponse(todoItem.getText().toString());
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
dialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
lastDialog = dialog;
}
public static void showEditDialog(Context context, String title, String defaultValue,
final DialogResponseListener editListener) {
final EditText todoItem = new EditText(context);
todoItem.setText(defaultValue);
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(title)
.setView(todoItem)
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
editListener.handleResponse(todoItem.getText().toString());
}
})
.setNeutralButton("Delete", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
editListener.handleDelete();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
dialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
lastDialog = dialog;
}
public static abstract class DialogResponseListener {
public abstract void handleResponse(String response);
public void handleDelete() {
}
}
// The share dialog contains two recycler views. The top one shows the existing items, and the
// bottom shows ones that are nearby but not shared to yet. There's also a freeform text box
// to allow entry of any value.
// Confirming this dialog sends the set of added and removed emails. Tap to add/remove.
public static void showShareDialog(Context context, List<String> existing, List<String> nearby,
final ShareDialogResponseListener shareListener) {
final Set<String> emailsRemoved = new HashSet<>();
final Set<String> emailsAdded = new HashSet<>();
final List<String> manualEmailsTyped = new ArrayList<>();
View sharingView = View.inflate(context, R.layout.sharing, null);
final RecyclerView rvAlready = (RecyclerView) sharingView.findViewById(R.id
.recycler_already);
rvAlready.setAdapter(new ContactAdapter(existing, emailsRemoved, true));
final RecyclerView rvPossible = (RecyclerView) sharingView.findViewById(R.id
.recycler_possible);
rvPossible.setAdapter(new ContactAdapter(nearby, manualEmailsTyped, emailsAdded, false));
final EditText editText = (EditText) sharingView.findViewById(R.id.custom_email);
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_SEND) {
String email = editText.getText().toString();
if (!manualEmailsTyped.contains(email)) {
manualEmailsTyped.add(email);
}
emailsAdded.add(email);
rvPossible.getAdapter().notifyDataSetChanged();
editText.setText("");
handled = true;
}
return handled;
}
});
new AlertDialog.Builder(context)
.setView(sharingView)
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
shareListener.handleShareChanges(emailsAdded, emailsRemoved);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
}
public interface ShareDialogResponseListener {
void handleShareChanges(Set<String> emailsAdded, Set<String> emailsRemoved);
}
private static class ContactAdapter extends RecyclerView.Adapter<ContactViewHolder> {
private final List<String> backup;
private final List<String> bonus;
private final Set<String> toggledOn;
private final boolean strikethrough; // If false, then bold.
public ContactAdapter(List<String> backup, Set<String> toggledOn, boolean strikethrough) {
super();
this.backup = backup;
this.bonus = null;
this.toggledOn = toggledOn;
this.strikethrough = strikethrough;
}
public ContactAdapter(List<String> backup, List<String> bonus, Set<String> toggledOn,
boolean strikethrough) {
super();
this.backup = backup;
this.bonus = bonus;
this.toggledOn = toggledOn;
this.strikethrough = strikethrough;
}
@Override
public ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ContactViewHolder(new TextView(parent.getContext()));
}
@Override
public void onBindViewHolder(final ContactViewHolder holder, int position) {
final String name = position < backup.size() ? backup.get(position) :
bonus.get(position - backup.size());
final boolean present = toggledOn.contains(name);
holder.bindString(name, present, strikethrough, new View.OnClickListener() {
@Override
public void onClick(View view) {
if (present) {
toggledOn.remove(name);
} else {
toggledOn.add(name);
}
notifyItemChanged(holder.getAdapterPosition());
}
});
}
@Override
public int getItemCount() {
int extra = bonus == null ? 0 : bonus.size();
return backup.size() + extra;
}
}
private static class ContactViewHolder extends RecyclerView.ViewHolder {
public ContactViewHolder(View itemView) {
super(itemView);
}
public void bindString(String name, boolean isActive, boolean strikethrough, View
.OnClickListener listener) {
TextView text = (TextView) itemView;
text.setText(name);
text.setTextSize(18);
if (strikethrough) {
if (isActive) {
text.setPaintFlags(text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
text.setPaintFlags(text.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
} else {
// We should bold!
if (isActive) {
text.setTypeface(null, 1); // 1 is bold
} else {
text.setTypeface(null, 0); // 0 is default text style
}
}
text.setOnClickListener(listener);
}
}
}