|
|
|
@ -16,22 +16,11 @@
|
|
|
|
|
|
|
|
|
|
package org.isoron.uhabits.fragments;
|
|
|
|
|
|
|
|
|
|
import android.animation.Animator;
|
|
|
|
|
import android.animation.AnimatorListenerAdapter;
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
import android.app.AlertDialog;
|
|
|
|
|
import android.app.Fragment;
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
|
import android.graphics.Color;
|
|
|
|
|
import android.graphics.Typeface;
|
|
|
|
|
import android.net.Uri;
|
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
|
import android.util.DisplayMetrics;
|
|
|
|
|
import android.view.ActionMode;
|
|
|
|
|
import android.view.ContextMenu;
|
|
|
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
|
|
|
@ -46,293 +35,100 @@ import android.view.ViewGroup;
|
|
|
|
|
import android.widget.AdapterView;
|
|
|
|
|
import android.widget.AdapterView.AdapterContextMenuInfo;
|
|
|
|
|
import android.widget.AdapterView.OnItemClickListener;
|
|
|
|
|
import android.widget.BaseAdapter;
|
|
|
|
|
import android.widget.Button;
|
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
|
import android.widget.LinearLayout.LayoutParams;
|
|
|
|
|
import android.widget.ProgressBar;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
|
|
import com.android.colorpicker.ColorPickerDialog;
|
|
|
|
|
import com.android.colorpicker.ColorPickerSwatch;
|
|
|
|
|
import com.mobeta.android.dslv.DragSortController;
|
|
|
|
|
import com.mobeta.android.dslv.DragSortListView;
|
|
|
|
|
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
|
|
|
|
|
|
|
|
|
import org.isoron.helpers.ColorHelper;
|
|
|
|
|
import org.isoron.helpers.Command;
|
|
|
|
|
import org.isoron.helpers.DateHelper;
|
|
|
|
|
import org.isoron.helpers.DialogHelper;
|
|
|
|
|
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
|
|
|
|
import org.isoron.helpers.ReplayableActivity;
|
|
|
|
|
import org.isoron.uhabits.R;
|
|
|
|
|
import org.isoron.uhabits.commands.ArchiveHabitsCommand;
|
|
|
|
|
import org.isoron.uhabits.commands.ChangeHabitColorCommand;
|
|
|
|
|
import org.isoron.uhabits.commands.DeleteHabitsCommand;
|
|
|
|
|
import org.isoron.uhabits.commands.ToggleRepetitionCommand;
|
|
|
|
|
import org.isoron.uhabits.commands.UnarchiveHabitsCommand;
|
|
|
|
|
import org.isoron.uhabits.dialogs.HabitSelectionCallback;
|
|
|
|
|
import org.isoron.uhabits.dialogs.HintManager;
|
|
|
|
|
import org.isoron.uhabits.helpers.ListHabitsHelper;
|
|
|
|
|
import org.isoron.uhabits.helpers.ReminderHelper;
|
|
|
|
|
import org.isoron.uhabits.io.CSVExporter;
|
|
|
|
|
import org.isoron.uhabits.loaders.HabitListLoader;
|
|
|
|
|
import org.isoron.uhabits.models.Habit;
|
|
|
|
|
import org.isoron.uhabits.models.Score;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.GregorianCalendar;
|
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
public class ListHabitsFragment extends Fragment
|
|
|
|
|
implements OnSavedListener, OnItemClickListener, OnLongClickListener, DropListener,
|
|
|
|
|
OnClickListener, HabitListLoader.Listener, AdapterView.OnItemLongClickListener
|
|
|
|
|
OnClickListener, HabitListLoader.Listener, AdapterView.OnItemLongClickListener,
|
|
|
|
|
HabitSelectionCallback.Listener
|
|
|
|
|
{
|
|
|
|
|
private class ListHabitsActionBarCallback implements ActionMode.Callback
|
|
|
|
|
{
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onCreateActionMode(ActionMode mode, Menu menu)
|
|
|
|
|
{
|
|
|
|
|
getActivity().getMenuInflater().inflate(R.menu.list_habits_context, menu);
|
|
|
|
|
updateTitle(mode);
|
|
|
|
|
updateActions(menu);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
|
|
|
|
|
{
|
|
|
|
|
updateTitle(mode);
|
|
|
|
|
updateActions(menu);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateActions(Menu menu)
|
|
|
|
|
{
|
|
|
|
|
boolean showEdit = (selectedPositions.size() == 1);
|
|
|
|
|
boolean showColor = true;
|
|
|
|
|
boolean showArchive = true;
|
|
|
|
|
boolean showUnarchive = true;
|
|
|
|
|
|
|
|
|
|
if(showEdit) showColor = false;
|
|
|
|
|
for(int i : selectedPositions)
|
|
|
|
|
{
|
|
|
|
|
Habit h = loader.habitsList.get(i);
|
|
|
|
|
if(h.isArchived())
|
|
|
|
|
{
|
|
|
|
|
showColor = false;
|
|
|
|
|
showArchive = false;
|
|
|
|
|
}
|
|
|
|
|
else showUnarchive = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MenuItem itemEdit = menu.findItem(R.id.action_edit_habit);
|
|
|
|
|
MenuItem itemColor = menu.findItem(R.id.action_color);
|
|
|
|
|
MenuItem itemArchive = menu.findItem(R.id.action_archive_habit);
|
|
|
|
|
MenuItem itemUnarchive = menu.findItem(R.id.action_unarchive_habit);
|
|
|
|
|
|
|
|
|
|
itemEdit.setVisible(showEdit);
|
|
|
|
|
itemColor.setVisible(showColor);
|
|
|
|
|
itemArchive.setVisible(showArchive);
|
|
|
|
|
itemUnarchive.setVisible(showUnarchive);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateTitle(ActionMode mode)
|
|
|
|
|
{
|
|
|
|
|
mode.setTitle("" + selectedPositions.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onActionItemClicked(final ActionMode mode, MenuItem item)
|
|
|
|
|
{
|
|
|
|
|
final LinkedList<Habit> selectedHabits = new LinkedList<>();
|
|
|
|
|
for(int i : selectedPositions)
|
|
|
|
|
selectedHabits.add(loader.habitsList.get(i));
|
|
|
|
|
|
|
|
|
|
Habit firstHabit = selectedHabits.getFirst();
|
|
|
|
|
|
|
|
|
|
switch(item.getItemId())
|
|
|
|
|
{
|
|
|
|
|
case R.id.action_archive_habit:
|
|
|
|
|
executeCommand(new ArchiveHabitsCommand(selectedHabits), null);
|
|
|
|
|
mode.finish();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case R.id.action_unarchive_habit:
|
|
|
|
|
executeCommand(new UnarchiveHabitsCommand(selectedHabits), null);
|
|
|
|
|
mode.finish();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case R.id.action_edit_habit:
|
|
|
|
|
{
|
|
|
|
|
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(firstHabit.getId());
|
|
|
|
|
frag.setOnSavedListener(ListHabitsFragment.this);
|
|
|
|
|
frag.show(getFragmentManager(), "dialog");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case R.id.action_color:
|
|
|
|
|
{
|
|
|
|
|
ColorPickerDialog picker = ColorPickerDialog.newInstance(
|
|
|
|
|
R.string.color_picker_default_title, ColorHelper.palette,
|
|
|
|
|
firstHabit.color, 4, ColorPickerDialog.SIZE_SMALL);
|
|
|
|
|
|
|
|
|
|
picker.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener()
|
|
|
|
|
{
|
|
|
|
|
public void onColorSelected(int color)
|
|
|
|
|
{
|
|
|
|
|
executeCommand(new ChangeHabitColorCommand(selectedHabits, color), null);
|
|
|
|
|
mode.finish();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
picker.show(getFragmentManager(), "picker");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case R.id.action_delete:
|
|
|
|
|
{
|
|
|
|
|
new AlertDialog.Builder(activity)
|
|
|
|
|
.setTitle(R.string.delete_habits)
|
|
|
|
|
.setMessage(R.string.delete_habits_message)
|
|
|
|
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener()
|
|
|
|
|
{
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(DialogInterface dialog, int which)
|
|
|
|
|
{
|
|
|
|
|
executeCommand(new DeleteHabitsCommand(selectedHabits), null);
|
|
|
|
|
mode.finish();
|
|
|
|
|
}
|
|
|
|
|
}).setNegativeButton(android.R.string.no, null)
|
|
|
|
|
.show();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case R.id.action_export_csv:
|
|
|
|
|
{
|
|
|
|
|
onExportHabitsClick(selectedHabits);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onDestroyActionMode(ActionMode mode)
|
|
|
|
|
{
|
|
|
|
|
actionMode = null;
|
|
|
|
|
|
|
|
|
|
selectedPositions.clear();
|
|
|
|
|
adapter.notifyDataSetChanged();
|
|
|
|
|
|
|
|
|
|
listView.setDragEnabled(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static final int INACTIVE_COLOR = Color.rgb(200, 200, 200);
|
|
|
|
|
public static final int INACTIVE_CHECKMARK_COLOR = Color.rgb(230, 230, 230);
|
|
|
|
|
|
|
|
|
|
public static final int HINT_INTERVAL = 5;
|
|
|
|
|
public static final int HINT_INTERVAL_OFFSET = 2;
|
|
|
|
|
|
|
|
|
|
public interface OnHabitClickListener
|
|
|
|
|
{
|
|
|
|
|
void onHabitClicked(Habit habit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListHabitsAdapter adapter;
|
|
|
|
|
DragSortListView listView;
|
|
|
|
|
ReplayableActivity activity;
|
|
|
|
|
TextView tvNameHeader;
|
|
|
|
|
long lastLongClick = 0;
|
|
|
|
|
|
|
|
|
|
private int tvNameWidth;
|
|
|
|
|
private int buttonCount;
|
|
|
|
|
private View llEmpty;
|
|
|
|
|
private View llHint;
|
|
|
|
|
|
|
|
|
|
private OnHabitClickListener habitClickListener;
|
|
|
|
|
private boolean isShortToggleEnabled;
|
|
|
|
|
|
|
|
|
|
private HabitListLoader loader;
|
|
|
|
|
private boolean showArchived;
|
|
|
|
|
private SharedPreferences prefs;
|
|
|
|
|
|
|
|
|
|
private ActionMode actionMode;
|
|
|
|
|
private HabitListAdapter adapter;
|
|
|
|
|
private HabitListLoader loader;
|
|
|
|
|
private HintManager hintManager;
|
|
|
|
|
private ListHabitsHelper helper;
|
|
|
|
|
private List<Integer> selectedPositions;
|
|
|
|
|
private DragSortController dragSortController;
|
|
|
|
|
private OnHabitClickListener habitClickListener;
|
|
|
|
|
private ReplayableActivity activity;
|
|
|
|
|
private SharedPreferences prefs;
|
|
|
|
|
|
|
|
|
|
private DragSortListView listView;
|
|
|
|
|
private LinearLayout llButtonsHeader;
|
|
|
|
|
private ProgressBar progressBar;
|
|
|
|
|
private View llEmpty;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
|
Bundle savedInstanceState)
|
|
|
|
|
{
|
|
|
|
|
DisplayMetrics dm = getResources().getDisplayMetrics();
|
|
|
|
|
int width = (int) (dm.widthPixels / dm.density);
|
|
|
|
|
buttonCount = Math.max(0, (int) ((width - 160) / 42.0));
|
|
|
|
|
tvNameWidth = (int) ((width - 30 - buttonCount * 42) * dm.density);
|
|
|
|
|
View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
|
|
|
|
|
View llHint = view.findViewById(R.id.llHint);
|
|
|
|
|
TextView tvStarEmpty = (TextView) view.findViewById(R.id.tvStarEmpty);
|
|
|
|
|
listView = (DragSortListView) view.findViewById(R.id.listView);
|
|
|
|
|
llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
|
|
|
|
|
llEmpty = view.findViewById(R.id.llEmpty);
|
|
|
|
|
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
|
|
|
|
|
|
|
|
|
selectedPositions = new LinkedList<>();
|
|
|
|
|
loader = new HabitListLoader();
|
|
|
|
|
helper = new ListHabitsHelper(activity, loader);
|
|
|
|
|
hintManager = new HintManager(activity, llHint);
|
|
|
|
|
|
|
|
|
|
loader.setListener(this);
|
|
|
|
|
loader.setCheckmarkCount(buttonCount);
|
|
|
|
|
loader.setCheckmarkCount(helper.getButtonCount());
|
|
|
|
|
loader.setProgressBar(progressBar);
|
|
|
|
|
|
|
|
|
|
View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
|
|
|
|
|
tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader);
|
|
|
|
|
llHint.setOnClickListener(this);
|
|
|
|
|
tvStarEmpty.setTypeface(helper.getFontawesome());
|
|
|
|
|
|
|
|
|
|
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
|
|
|
|
loader.setProgressBar(progressBar);
|
|
|
|
|
adapter = new HabitListAdapter(getActivity(), loader);
|
|
|
|
|
adapter.setSelectedPositions(selectedPositions);
|
|
|
|
|
adapter.setOnCheckmarkClickListener(this);
|
|
|
|
|
adapter.setOnCheckmarkLongClickListener(this);
|
|
|
|
|
|
|
|
|
|
DragSortListView.DragListener dragListener = new HabitsDragListener();
|
|
|
|
|
DragSortController dragSortController = new HabitsDragSortController();
|
|
|
|
|
|
|
|
|
|
adapter = new ListHabitsAdapter(getActivity());
|
|
|
|
|
listView = (DragSortListView) view.findViewById(R.id.listView);
|
|
|
|
|
listView.setAdapter(adapter);
|
|
|
|
|
listView.setOnItemClickListener(this);
|
|
|
|
|
listView.setOnItemLongClickListener(this);
|
|
|
|
|
listView.setDropListener(this);
|
|
|
|
|
listView.setDragListener(new DragSortListView.DragListener()
|
|
|
|
|
{
|
|
|
|
|
@Override
|
|
|
|
|
public void drag(int from, int to)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void startDrag(int position)
|
|
|
|
|
{
|
|
|
|
|
selectItem(position);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
dragSortController = new DragSortController(listView) {
|
|
|
|
|
@Override
|
|
|
|
|
public View onCreateFloatView(int position)
|
|
|
|
|
{
|
|
|
|
|
return adapter.getView(position, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onDestroyFloatView(View floatView)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
dragSortController.setRemoveEnabled(false);
|
|
|
|
|
|
|
|
|
|
listView.setDragListener(dragListener);
|
|
|
|
|
listView.setFloatViewManager(dragSortController);
|
|
|
|
|
listView.setDragEnabled(true);
|
|
|
|
|
listView.setLongClickable(true);
|
|
|
|
|
|
|
|
|
|
llHint = view.findViewById(R.id.llHint);
|
|
|
|
|
llHint.setOnClickListener(this);
|
|
|
|
|
|
|
|
|
|
Typeface fontawesome = Typeface.createFromAsset(getActivity().getAssets(),
|
|
|
|
|
"fontawesome-webfont.ttf");
|
|
|
|
|
((TextView) view.findViewById(R.id.tvStarEmpty)).setTypeface(fontawesome);
|
|
|
|
|
llEmpty = view.findViewById(R.id.llEmpty);
|
|
|
|
|
|
|
|
|
|
loader.updateAllHabits(true);
|
|
|
|
|
setHasOptionsMenu(true);
|
|
|
|
|
|
|
|
|
|
selectedPositions = new LinkedList<>();
|
|
|
|
|
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -356,42 +152,19 @@ public class ListHabitsFragment extends Fragment
|
|
|
|
|
if (timestamp != null && timestamp != DateHelper.getStartOfToday())
|
|
|
|
|
loader.updateAllHabits(true);
|
|
|
|
|
|
|
|
|
|
updateEmptyMessage();
|
|
|
|
|
updateHeader();
|
|
|
|
|
showNextHint();
|
|
|
|
|
helper.updateEmptyMessage(llEmpty);
|
|
|
|
|
helper.updateHeader(llButtonsHeader);
|
|
|
|
|
hintManager.showHintIfAppropriate();
|
|
|
|
|
|
|
|
|
|
adapter.notifyDataSetChanged();
|
|
|
|
|
isShortToggleEnabled = prefs.getBoolean("pref_short_toggle", false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateHeader()
|
|
|
|
|
{
|
|
|
|
|
LayoutInflater inflater = activity.getLayoutInflater();
|
|
|
|
|
View view = getView();
|
|
|
|
|
|
|
|
|
|
if (view == null) return;
|
|
|
|
|
|
|
|
|
|
GregorianCalendar day = DateHelper.getStartOfTodayCalendar();
|
|
|
|
|
|
|
|
|
|
LinearLayout llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
|
|
|
|
|
llButtonsHeader.removeAllViews();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < buttonCount; i++)
|
|
|
|
|
{
|
|
|
|
|
View tvDay = inflater.inflate(R.layout.list_habits_header_check, null);
|
|
|
|
|
Button btCheck = (Button) tvDay.findViewById(R.id.tvCheck);
|
|
|
|
|
btCheck.setText(DateHelper.formatHeaderDate(day));
|
|
|
|
|
llButtonsHeader.addView(tvDay);
|
|
|
|
|
|
|
|
|
|
day.add(GregorianCalendar.DAY_OF_MONTH, -1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onLoadFinished()
|
|
|
|
|
{
|
|
|
|
|
adapter.notifyDataSetChanged();
|
|
|
|
|
updateEmptyMessage();
|
|
|
|
|
helper.updateEmptyMessage(llEmpty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -485,8 +258,13 @@ public class ListHabitsFragment extends Fragment
|
|
|
|
|
|
|
|
|
|
if(actionMode == null)
|
|
|
|
|
{
|
|
|
|
|
actionMode = getActivity().startActionMode(new ListHabitsActionBarCallback());
|
|
|
|
|
// listView.setDragEnabled(false);
|
|
|
|
|
HabitSelectionCallback callback = new HabitSelectionCallback(activity, loader);
|
|
|
|
|
callback.setSelectedPositions(selectedPositions);
|
|
|
|
|
callback.setProgressBar(progressBar);
|
|
|
|
|
callback.setOnSavedListener(this);
|
|
|
|
|
callback.setListener(this);
|
|
|
|
|
|
|
|
|
|
actionMode = getActivity().startActionMode(callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(actionMode != null) actionMode.invalidate();
|
|
|
|
@ -506,12 +284,6 @@ public class ListHabitsFragment extends Fragment
|
|
|
|
|
if(actionMode != null) actionMode.finish();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateEmptyMessage()
|
|
|
|
|
{
|
|
|
|
|
if (loader.getLastLoadTimestamp() == null) llEmpty.setVisibility(View.GONE);
|
|
|
|
|
else llEmpty.setVisibility(loader.habits.size() > 0 ? View.GONE : View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onLongClick(View v)
|
|
|
|
|
{
|
|
|
|
@ -538,15 +310,14 @@ public class ListHabitsFragment extends Fragment
|
|
|
|
|
private void toggleCheck(View v)
|
|
|
|
|
{
|
|
|
|
|
Long tag = (Long) v.getTag(R.string.habit_key);
|
|
|
|
|
Habit habit = loader.habits.get(tag);
|
|
|
|
|
|
|
|
|
|
int offset = (Integer) v.getTag(R.string.offset_key);
|
|
|
|
|
Integer offset = (Integer) v.getTag(R.string.offset_key);
|
|
|
|
|
long timestamp = DateHelper.getStartOfDay(
|
|
|
|
|
DateHelper.getLocalTime() - offset * DateHelper.millisecondsInOneDay);
|
|
|
|
|
|
|
|
|
|
if (v.getTag(R.string.toggle_key).equals(2)) updateCheckmark(habit.color, (TextView) v, 0);
|
|
|
|
|
else updateCheckmark(habit.color, (TextView) v, 2);
|
|
|
|
|
Habit habit = loader.habits.get(tag);
|
|
|
|
|
if(habit == null) return;
|
|
|
|
|
|
|
|
|
|
helper.toggleCheckmarkView(v, habit);
|
|
|
|
|
executeCommand(new ToggleRepetitionCommand(habit, timestamp), habit.getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -555,43 +326,6 @@ public class ListHabitsFragment extends Fragment
|
|
|
|
|
activity.executeCommand(c, refreshKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void hideHint()
|
|
|
|
|
{
|
|
|
|
|
llHint.animate().alpha(0f).setDuration(500).setListener(new AnimatorListenerAdapter()
|
|
|
|
|
{
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation)
|
|
|
|
|
{
|
|
|
|
|
llHint.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showNextHint()
|
|
|
|
|
{
|
|
|
|
|
Integer lastHintNumber = prefs.getInt("last_hint_number", -1);
|
|
|
|
|
Long lastHintTimestamp = prefs.getLong("last_hint_timestamp", -1);
|
|
|
|
|
|
|
|
|
|
if(DateHelper.getStartOfToday() > lastHintTimestamp)
|
|
|
|
|
showHint(lastHintNumber + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showHint(int hintNumber)
|
|
|
|
|
{
|
|
|
|
|
String[] hints = activity.getResources().getStringArray(R.array.hints);
|
|
|
|
|
if(hintNumber >= hints.length) return;
|
|
|
|
|
|
|
|
|
|
prefs.edit().putInt("last_hint_number", hintNumber).apply();
|
|
|
|
|
prefs.edit().putLong("last_hint_timestamp", DateHelper.getStartOfToday()).apply();
|
|
|
|
|
|
|
|
|
|
TextView tvContent = (TextView) llHint.findViewById(R.id.hintContent);
|
|
|
|
|
tvContent.setText(hints[hintNumber]);
|
|
|
|
|
|
|
|
|
|
llHint.setAlpha(0.0f);
|
|
|
|
|
llHint.setVisibility(View.VISIBLE);
|
|
|
|
|
llHint.animate().alpha(1f).setDuration(500);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void drop(int from, int to)
|
|
|
|
|
{
|
|
|
|
@ -614,226 +348,61 @@ public class ListHabitsFragment extends Fragment
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case R.id.llHint:
|
|
|
|
|
hideHint();
|
|
|
|
|
hintManager.dismissHint();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ListHabitsAdapter extends BaseAdapter
|
|
|
|
|
{
|
|
|
|
|
private LayoutInflater inflater;
|
|
|
|
|
private Typeface fontawesome;
|
|
|
|
|
|
|
|
|
|
public ListHabitsAdapter(Context context)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
|
|
|
fontawesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int getCount()
|
|
|
|
|
{
|
|
|
|
|
return loader.habits.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Object getItem(int position)
|
|
|
|
|
{
|
|
|
|
|
return loader.habitsList.get(position);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public long getItemId(int position)
|
|
|
|
|
{
|
|
|
|
|
return ((Habit) getItem(position)).getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public View getView(int position, View view, ViewGroup parent)
|
|
|
|
|
{
|
|
|
|
|
final Habit habit = loader.habitsList.get(position);
|
|
|
|
|
|
|
|
|
|
if (view == null ||
|
|
|
|
|
(Long) view.getTag(R.id.timestamp_key) != DateHelper.getStartOfToday())
|
|
|
|
|
{
|
|
|
|
|
view = inflater.inflate(R.layout.list_habits_item, null);
|
|
|
|
|
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
|
|
|
|
|
|
|
|
|
|
LinearLayout.LayoutParams params =
|
|
|
|
|
new LinearLayout.LayoutParams(tvNameWidth, LayoutParams.WRAP_CONTENT, 1);
|
|
|
|
|
view.findViewById(R.id.label).setLayoutParams(params);
|
|
|
|
|
|
|
|
|
|
inflateCheckmarkButtons(view);
|
|
|
|
|
|
|
|
|
|
view.setTag(R.id.timestamp_key, DateHelper.getStartOfToday());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TextView tvStar = ((TextView) view.findViewById(R.id.tvStar));
|
|
|
|
|
TextView tvName = (TextView) view.findViewById(R.id.label);
|
|
|
|
|
LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
|
|
|
|
|
LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons);
|
|
|
|
|
|
|
|
|
|
llInner.setTag(R.string.habit_key, habit.getId());
|
|
|
|
|
|
|
|
|
|
updateNameAndIcon(habit, tvStar, tvName);
|
|
|
|
|
updateCheckmarkButtons(habit, llButtons);
|
|
|
|
|
|
|
|
|
|
boolean selected = selectedPositions.contains(position);
|
|
|
|
|
if(selected)
|
|
|
|
|
llInner.setBackgroundResource(R.drawable.selected_box);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 21)
|
|
|
|
|
llInner.setBackgroundResource(R.drawable.ripple_white);
|
|
|
|
|
else
|
|
|
|
|
llInner.setBackgroundResource(R.drawable.card_background);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void inflateCheckmarkButtons(View view)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < buttonCount; i++)
|
|
|
|
|
public void onPostExecuteCommand(Long refreshKey)
|
|
|
|
|
{
|
|
|
|
|
View check = inflater.inflate(R.layout.list_habits_item_check, null);
|
|
|
|
|
TextView btCheck = (TextView) check.findViewById(R.id.tvCheck);
|
|
|
|
|
btCheck.setTypeface(fontawesome);
|
|
|
|
|
btCheck.setOnLongClickListener(ListHabitsFragment.this);
|
|
|
|
|
btCheck.setOnClickListener(ListHabitsFragment.this);
|
|
|
|
|
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (refreshKey == null) loader.updateAllHabits(true);
|
|
|
|
|
else loader.updateHabit(refreshKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateCheckmarkButtons(Habit habit, LinearLayout llButtons)
|
|
|
|
|
{
|
|
|
|
|
int activeColor = getActiveColor(habit);
|
|
|
|
|
int m = llButtons.getChildCount();
|
|
|
|
|
Long habitId = habit.getId();
|
|
|
|
|
|
|
|
|
|
int isChecked[] = loader.checkmarks.get(habitId);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < m; i++)
|
|
|
|
|
public void onActionModeDestroyed(ActionMode mode)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
TextView tvCheck = (TextView) llButtons.getChildAt(i);
|
|
|
|
|
tvCheck.setTag(R.string.habit_key, habitId);
|
|
|
|
|
tvCheck.setTag(R.string.offset_key, i);
|
|
|
|
|
if(isChecked.length > i)
|
|
|
|
|
updateCheckmark(activeColor, tvCheck, isChecked[i]);
|
|
|
|
|
}
|
|
|
|
|
actionMode = null;
|
|
|
|
|
selectedPositions.clear();
|
|
|
|
|
adapter.notifyDataSetChanged();
|
|
|
|
|
listView.setDragEnabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateNameAndIcon(Habit habit, TextView tvStar, TextView tvName)
|
|
|
|
|
{
|
|
|
|
|
int activeColor = getActiveColor(habit);
|
|
|
|
|
|
|
|
|
|
tvName.setText(habit.name);
|
|
|
|
|
tvName.setTextColor(activeColor);
|
|
|
|
|
|
|
|
|
|
if (habit.isArchived())
|
|
|
|
|
public interface OnHabitClickListener
|
|
|
|
|
{
|
|
|
|
|
tvStar.setText(getString(R.string.fa_archive));
|
|
|
|
|
tvStar.setTextColor(activeColor);
|
|
|
|
|
void onHabitClicked(Habit habit);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int score = loader.scores.get(habit.getId());
|
|
|
|
|
|
|
|
|
|
if (score < Score.HALF_STAR_CUTOFF)
|
|
|
|
|
private class HabitsDragSortController extends DragSortController
|
|
|
|
|
{
|
|
|
|
|
tvStar.setText(getString(R.string.fa_star_o));
|
|
|
|
|
tvStar.setTextColor(INACTIVE_COLOR);
|
|
|
|
|
}
|
|
|
|
|
else if (score < Score.FULL_STAR_CUTOFF)
|
|
|
|
|
{
|
|
|
|
|
tvStar.setText(getString(R.string.fa_star_half_o));
|
|
|
|
|
tvStar.setTextColor(INACTIVE_COLOR);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
public HabitsDragSortController()
|
|
|
|
|
{
|
|
|
|
|
tvStar.setText(getString(R.string.fa_star));
|
|
|
|
|
tvStar.setTextColor(activeColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
super(ListHabitsFragment.this.listView);
|
|
|
|
|
setRemoveEnabled(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int getActiveColor(Habit habit)
|
|
|
|
|
@Override
|
|
|
|
|
public View onCreateFloatView(int position)
|
|
|
|
|
{
|
|
|
|
|
int activeColor = habit.color;
|
|
|
|
|
if(habit.isArchived()) activeColor = INACTIVE_COLOR;
|
|
|
|
|
|
|
|
|
|
return activeColor;
|
|
|
|
|
return adapter.getView(position, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateCheckmark(int activeColor, TextView tvCheck, int check)
|
|
|
|
|
{
|
|
|
|
|
switch (check)
|
|
|
|
|
@Override
|
|
|
|
|
public void onDestroyFloatView(View floatView)
|
|
|
|
|
{
|
|
|
|
|
case 2:
|
|
|
|
|
tvCheck.setText(R.string.fa_check);
|
|
|
|
|
tvCheck.setTextColor(activeColor);
|
|
|
|
|
tvCheck.setTag(R.string.toggle_key, 2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
tvCheck.setText(R.string.fa_check);
|
|
|
|
|
tvCheck.setTextColor(INACTIVE_CHECKMARK_COLOR);
|
|
|
|
|
tvCheck.setTag(R.string.toggle_key, 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
|
tvCheck.setText(R.string.fa_times);
|
|
|
|
|
tvCheck.setTextColor(INACTIVE_CHECKMARK_COLOR);
|
|
|
|
|
tvCheck.setTag(R.string.toggle_key, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onPostExecuteCommand(Long refreshKey)
|
|
|
|
|
private class HabitsDragListener implements DragSortListView.DragListener
|
|
|
|
|
{
|
|
|
|
|
if (refreshKey == null) loader.updateAllHabits(true);
|
|
|
|
|
else loader.updateHabit(refreshKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onExportHabitsClick(final LinkedList<Habit> selectedHabits)
|
|
|
|
|
{
|
|
|
|
|
new AsyncTask<Void, Void, Void>()
|
|
|
|
|
{
|
|
|
|
|
String filename;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onPreExecute()
|
|
|
|
|
{
|
|
|
|
|
progressBar.setIndeterminate(true);
|
|
|
|
|
progressBar.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onPostExecute(Void aVoid)
|
|
|
|
|
{
|
|
|
|
|
if(filename != null)
|
|
|
|
|
public void drag(int from, int to)
|
|
|
|
|
{
|
|
|
|
|
Intent intent = new Intent();
|
|
|
|
|
intent.setAction(Intent.ACTION_SEND);
|
|
|
|
|
intent.setType("application/zip");
|
|
|
|
|
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filename)));
|
|
|
|
|
|
|
|
|
|
startActivity(intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
progressBar.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected Void doInBackground(Void... params)
|
|
|
|
|
public void startDrag(int position)
|
|
|
|
|
{
|
|
|
|
|
CSVExporter exporter = new CSVExporter(activity, selectedHabits);
|
|
|
|
|
filename = exporter.writeArchive();
|
|
|
|
|
return null;
|
|
|
|
|
selectItem(position);
|
|
|
|
|
}
|
|
|
|
|
}.execute();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|