mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Merge branch 'feature/numerical' into dev
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -16,3 +16,7 @@ captures
|
|||||||
local.properties
|
local.properties
|
||||||
node_modules
|
node_modules
|
||||||
*xcuserdata*
|
*xcuserdata*
|
||||||
|
*.sketch
|
||||||
|
/design
|
||||||
|
/releases
|
||||||
|
/screenshots
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ public class AmPmCirclesView extends View {
|
|||||||
private final Paint mPaint = new Paint();
|
private final Paint mPaint = new Paint();
|
||||||
private int mSelectedAlpha;
|
private int mSelectedAlpha;
|
||||||
private int mUnselectedColor;
|
private int mUnselectedColor;
|
||||||
private int mAmPmTextColor;
|
protected int mAmPmTextColor = Color.WHITE;
|
||||||
private int mSelectedColor;
|
protected int mSelectedColor = Color.BLUE;
|
||||||
private float mCircleRadiusMultiplier;
|
private float mCircleRadiusMultiplier;
|
||||||
private float mAmPmCircleRadiusMultiplier;
|
private float mAmPmCircleRadiusMultiplier;
|
||||||
private String mAmText;
|
private String mAmText;
|
||||||
@@ -73,8 +73,8 @@ public class AmPmCirclesView extends View {
|
|||||||
|
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
mUnselectedColor = res.getColor(R.color.white);
|
mUnselectedColor = res.getColor(R.color.white);
|
||||||
mSelectedColor = res.getColor(R.color.blue);
|
//mSelectedColor = res.getColor(R.color.blue);
|
||||||
mAmPmTextColor = res.getColor(R.color.ampm_text_color);
|
//mAmPmTextColor = res.getColor(R.color.ampm_text_color);
|
||||||
mSelectedAlpha = SELECTED_ALPHA;
|
mSelectedAlpha = SELECTED_ALPHA;
|
||||||
String typefaceFamily = res.getString(R.string.sans_serif);
|
String typefaceFamily = res.getString(R.string.sans_serif);
|
||||||
Typeface tf = Typeface.create(typefaceFamily, Typeface.NORMAL);
|
Typeface tf = Typeface.create(typefaceFamily, Typeface.NORMAL);
|
||||||
@@ -105,8 +105,8 @@ public class AmPmCirclesView extends View {
|
|||||||
mSelectedAlpha = SELECTED_ALPHA_THEME_DARK;
|
mSelectedAlpha = SELECTED_ALPHA_THEME_DARK;
|
||||||
} else {
|
} else {
|
||||||
mUnselectedColor = res.getColor(R.color.white);
|
mUnselectedColor = res.getColor(R.color.white);
|
||||||
mSelectedColor = res.getColor(R.color.blue);
|
//mSelectedColor = res.getColor(R.color.blue);
|
||||||
mAmPmTextColor = res.getColor(R.color.ampm_text_color);
|
//mAmPmTextColor = res.getColor(R.color.ampm_text_color);
|
||||||
mSelectedAlpha = SELECTED_ALPHA;
|
mSelectedAlpha = SELECTED_ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,14 @@ public class RadialPickerLayout extends FrameLayout implements OnTouchListener {
|
|||||||
private AnimatorSet mTransition;
|
private AnimatorSet mTransition;
|
||||||
private Handler mHandler = new Handler();
|
private Handler mHandler = new Handler();
|
||||||
|
|
||||||
|
public void setColor(int selectedColor)
|
||||||
|
{
|
||||||
|
mHourRadialSelectorView.mPaint.setColor(selectedColor);
|
||||||
|
mMinuteRadialSelectorView.mPaint.setColor(selectedColor);
|
||||||
|
mAmPmCirclesView.mSelectedColor = selectedColor;
|
||||||
|
mAmPmCirclesView.mAmPmTextColor = selectedColor;
|
||||||
|
}
|
||||||
|
|
||||||
public interface OnValueSelectedListener {
|
public interface OnValueSelectedListener {
|
||||||
void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance);
|
void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class RadialSelectorView extends View {
|
|||||||
// Alpha level for the line.
|
// Alpha level for the line.
|
||||||
private static final int FULL_ALPHA = Utils.FULL_ALPHA;
|
private static final int FULL_ALPHA = Utils.FULL_ALPHA;
|
||||||
|
|
||||||
private final Paint mPaint = new Paint();
|
protected final Paint mPaint = new Paint();
|
||||||
|
|
||||||
private boolean mIsInitialized;
|
private boolean mIsInitialized;
|
||||||
private boolean mDrawValuesReady;
|
private boolean mDrawValuesReady;
|
||||||
@@ -96,8 +96,6 @@ public class RadialSelectorView extends View {
|
|||||||
|
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
|
|
||||||
int blue = res.getColor(R.color.blue);
|
|
||||||
mPaint.setColor(blue);
|
|
||||||
mPaint.setAntiAlias(true);
|
mPaint.setAntiAlias(true);
|
||||||
mSelectionAlpha = SELECTED_ALPHA;
|
mSelectionAlpha = SELECTED_ALPHA;
|
||||||
|
|
||||||
@@ -139,15 +137,11 @@ public class RadialSelectorView extends View {
|
|||||||
|
|
||||||
/* package */ void setTheme(Context context, boolean themeDark) {
|
/* package */ void setTheme(Context context, boolean themeDark) {
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
int color;
|
|
||||||
if (themeDark) {
|
if (themeDark) {
|
||||||
color = res.getColor(R.color.red);
|
|
||||||
mSelectionAlpha = SELECTED_ALPHA_THEME_DARK;
|
mSelectionAlpha = SELECTED_ALPHA_THEME_DARK;
|
||||||
} else {
|
} else {
|
||||||
color = res.getColor(R.color.blue);
|
|
||||||
mSelectionAlpha = SELECTED_ALPHA;
|
mSelectionAlpha = SELECTED_ALPHA;
|
||||||
}
|
}
|
||||||
mPaint.setColor(color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ import android.app.*;
|
|||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.content.res.*;
|
import android.content.res.*;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
|
|
||||||
import androidx.appcompat.app.*;
|
import androidx.appcompat.app.*;
|
||||||
|
|
||||||
import android.util.*;
|
import android.util.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.view.View.*;
|
import android.view.View.*;
|
||||||
@@ -39,7 +41,8 @@ import java.util.*;
|
|||||||
/**
|
/**
|
||||||
* Dialog to set a time.
|
* Dialog to set a time.
|
||||||
*/
|
*/
|
||||||
public class TimePickerDialog extends AppCompatDialogFragment implements OnValueSelectedListener{
|
public class TimePickerDialog extends AppCompatDialogFragment implements OnValueSelectedListener
|
||||||
|
{
|
||||||
private static final String TAG = "TimePickerDialog";
|
private static final String TAG = "TimePickerDialog";
|
||||||
|
|
||||||
private static final String KEY_HOUR_OF_DAY = "hour_of_day";
|
private static final String KEY_HOUR_OF_DAY = "hour_of_day";
|
||||||
@@ -49,6 +52,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
private static final String KEY_IN_KB_MODE = "in_kb_mode";
|
private static final String KEY_IN_KB_MODE = "in_kb_mode";
|
||||||
private static final String KEY_TYPED_TIMES = "typed_times";
|
private static final String KEY_TYPED_TIMES = "typed_times";
|
||||||
private static final String KEY_DARK_THEME = "dark_theme";
|
private static final String KEY_DARK_THEME = "dark_theme";
|
||||||
|
private static final String KEY_SELECTED_COLOR = "selected_color";
|
||||||
|
|
||||||
public static final int HOUR_INDEX = 0;
|
public static final int HOUR_INDEX = 0;
|
||||||
public static final int MINUTE_INDEX = 1;
|
public static final int MINUTE_INDEX = 1;
|
||||||
@@ -108,7 +112,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
* The callback interface used to indicate the user is done filling in
|
* The callback interface used to indicate the user is done filling in
|
||||||
* the time (they clicked on the 'Set' button).
|
* the time (they clicked on the 'Set' button).
|
||||||
*/
|
*/
|
||||||
public interface OnTimeSetListener {
|
public interface OnTimeSetListener
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param view The view associated with this listener.
|
* @param view The view associated with this listener.
|
||||||
@@ -117,28 +122,40 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
*/
|
*/
|
||||||
void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute);
|
void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute);
|
||||||
|
|
||||||
default void onTimeCleared(RadialPickerLayout view) {}
|
default void onTimeCleared(RadialPickerLayout view)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimePickerDialog() {
|
public TimePickerDialog()
|
||||||
|
{
|
||||||
// Empty constructor required for dialog fragment.
|
// Empty constructor required for dialog fragment.
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("Java")
|
@SuppressLint("Java")
|
||||||
public TimePickerDialog(Context context, int theme, OnTimeSetListener callback,
|
public TimePickerDialog(Context context, int theme, OnTimeSetListener callback,
|
||||||
int hourOfDay, int minute, boolean is24HourMode) {
|
int hourOfDay, int minute, boolean is24HourMode)
|
||||||
|
{
|
||||||
// Empty constructor required for dialog fragment.
|
// Empty constructor required for dialog fragment.
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TimePickerDialog newInstance(OnTimeSetListener callback,
|
public static TimePickerDialog newInstance(OnTimeSetListener callback,
|
||||||
int hourOfDay, int minute, boolean is24HourMode) {
|
int hourOfDay,
|
||||||
|
int minute,
|
||||||
|
boolean is24HourMode,
|
||||||
|
int color)
|
||||||
|
{
|
||||||
TimePickerDialog ret = new TimePickerDialog();
|
TimePickerDialog ret = new TimePickerDialog();
|
||||||
ret.initialize(callback, hourOfDay, minute, is24HourMode);
|
ret.initialize(callback, hourOfDay, minute, is24HourMode, color);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(OnTimeSetListener callback,
|
public void initialize(OnTimeSetListener callback,
|
||||||
int hourOfDay, int minute, boolean is24HourMode) {
|
int hourOfDay,
|
||||||
|
int minute,
|
||||||
|
boolean is24HourMode,
|
||||||
|
int color)
|
||||||
|
{
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
|
|
||||||
mInitialHourOfDay = hourOfDay;
|
mInitialHourOfDay = hourOfDay;
|
||||||
@@ -146,31 +163,37 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
mIs24HourMode = is24HourMode;
|
mIs24HourMode = is24HourMode;
|
||||||
mInKbMode = false;
|
mInKbMode = false;
|
||||||
mThemeDark = false;
|
mThemeDark = false;
|
||||||
|
mSelectedColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a dark or light theme. NOTE: this will only take effect for the next onCreateView.
|
* Set a dark or light theme. NOTE: this will only take effect for the next onCreateView.
|
||||||
*/
|
*/
|
||||||
public void setThemeDark(boolean dark) {
|
public void setThemeDark(boolean dark)
|
||||||
|
{
|
||||||
mThemeDark = dark;
|
mThemeDark = dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isThemeDark() {
|
public boolean isThemeDark()
|
||||||
|
{
|
||||||
return mThemeDark;
|
return mThemeDark;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTimeSetListener(OnTimeSetListener callback) {
|
public void setOnTimeSetListener(OnTimeSetListener callback)
|
||||||
|
{
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStartTime(int hourOfDay, int minute) {
|
public void setStartTime(int hourOfDay, int minute)
|
||||||
|
{
|
||||||
mInitialHourOfDay = hourOfDay;
|
mInitialHourOfDay = hourOfDay;
|
||||||
mInitialMinute = minute;
|
mInitialMinute = minute;
|
||||||
mInKbMode = false;
|
mInKbMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_HOUR_OF_DAY)
|
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_HOUR_OF_DAY)
|
||||||
&& savedInstanceState.containsKey(KEY_MINUTE)
|
&& savedInstanceState.containsKey(KEY_MINUTE)
|
||||||
@@ -180,6 +203,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
mIs24HourMode = savedInstanceState.getBoolean(KEY_IS_24_HOUR_VIEW);
|
mIs24HourMode = savedInstanceState.getBoolean(KEY_IS_24_HOUR_VIEW);
|
||||||
mInKbMode = savedInstanceState.getBoolean(KEY_IN_KB_MODE);
|
mInKbMode = savedInstanceState.getBoolean(KEY_IN_KB_MODE);
|
||||||
mThemeDark = savedInstanceState.getBoolean(KEY_DARK_THEME);
|
mThemeDark = savedInstanceState.getBoolean(KEY_DARK_THEME);
|
||||||
|
mSelectedColor = savedInstanceState.getInt(KEY_SELECTED_COLOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +215,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState)
|
||||||
|
{
|
||||||
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
|
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.time_picker_dialog, null);
|
View view = inflater.inflate(R.layout.time_picker_dialog, null);
|
||||||
@@ -203,8 +228,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
mSelectHours = res.getString(R.string.select_hours);
|
mSelectHours = res.getString(R.string.select_hours);
|
||||||
mMinutePickerDescription = res.getString(R.string.minute_picker_description);
|
mMinutePickerDescription = res.getString(R.string.minute_picker_description);
|
||||||
mSelectMinutes = res.getString(R.string.select_minutes);
|
mSelectMinutes = res.getString(R.string.select_minutes);
|
||||||
mSelectedColor = res.getColor(mThemeDark? R.color.red : R.color.blue);
|
//mSelectedColor = res.getColor(mThemeDark ? R.color.red : R.color.blue);
|
||||||
mUnselectedColor = res.getColor(mThemeDark? R.color.white : R.color.numbers_text_color);
|
mUnselectedColor = res.getColor(mThemeDark ? R.color.white : R.color.numbers_text_color);
|
||||||
|
|
||||||
mHourView = (TextView) view.findViewById(R.id.hours);
|
mHourView = (TextView) view.findViewById(R.id.hours);
|
||||||
mHourView.setOnKeyListener(keyboardListener);
|
mHourView.setOnKeyListener(keyboardListener);
|
||||||
@@ -223,6 +248,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
mTimePicker = (RadialPickerLayout) view.findViewById(R.id.time_picker);
|
mTimePicker = (RadialPickerLayout) view.findViewById(R.id.time_picker);
|
||||||
mTimePicker.setOnValueSelectedListener(this);
|
mTimePicker.setOnValueSelectedListener(this);
|
||||||
mTimePicker.setOnKeyListener(keyboardListener);
|
mTimePicker.setOnKeyListener(keyboardListener);
|
||||||
|
mTimePicker.setColor(mSelectedColor);
|
||||||
mTimePicker.initialize(getActivity(), mHapticFeedbackController, mInitialHourOfDay,
|
mTimePicker.initialize(getActivity(), mHapticFeedbackController, mInitialHourOfDay,
|
||||||
mInitialMinute, mIs24HourMode);
|
mInitialMinute, mIs24HourMode);
|
||||||
|
|
||||||
@@ -234,25 +260,31 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
setCurrentItemShowing(currentItemShowing, false, true, true);
|
setCurrentItemShowing(currentItemShowing, false, true, true);
|
||||||
mTimePicker.invalidate();
|
mTimePicker.invalidate();
|
||||||
|
|
||||||
mHourView.setOnClickListener(new OnClickListener() {
|
mHourView.setOnClickListener(new OnClickListener()
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v)
|
||||||
|
{
|
||||||
setCurrentItemShowing(HOUR_INDEX, true, false, true);
|
setCurrentItemShowing(HOUR_INDEX, true, false, true);
|
||||||
tryVibrate();
|
tryVibrate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mMinuteView.setOnClickListener(new OnClickListener() {
|
mMinuteView.setOnClickListener(new OnClickListener()
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v)
|
||||||
|
{
|
||||||
setCurrentItemShowing(MINUTE_INDEX, true, false, true);
|
setCurrentItemShowing(MINUTE_INDEX, true, false, true);
|
||||||
tryVibrate();
|
tryVibrate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mDoneButton = (TextView) view.findViewById(R.id.done_button);
|
mDoneButton = (TextView) view.findViewById(R.id.done_button);
|
||||||
mDoneButton.setOnClickListener(new OnClickListener() {
|
mDoneButton.setOnClickListener(new OnClickListener()
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v)
|
||||||
|
{
|
||||||
if (mInKbMode && isTypedTimeFullyLegal()) {
|
if (mInKbMode && isTypedTimeFullyLegal()) {
|
||||||
finishKbMode(false);
|
finishKbMode(false);
|
||||||
} else {
|
} else {
|
||||||
@@ -273,7 +305,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v)
|
public void onClick(View v)
|
||||||
{
|
{
|
||||||
if(mCallback != null) {
|
if (mCallback != null) {
|
||||||
mCallback.onTimeCleared(mTimePicker);
|
mCallback.onTimeCleared(mTimePicker);
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
@@ -293,15 +325,17 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
separatorView.setLayoutParams(paramsSeparator);
|
separatorView.setLayoutParams(paramsSeparator);
|
||||||
} else {
|
} else {
|
||||||
mAmPmTextView.setVisibility(View.VISIBLE);
|
mAmPmTextView.setVisibility(View.VISIBLE);
|
||||||
updateAmPmDisplay(mInitialHourOfDay < 12? AM : PM);
|
updateAmPmDisplay(mInitialHourOfDay < 12 ? AM : PM);
|
||||||
mAmPmHitspace.setOnClickListener(new OnClickListener() {
|
mAmPmHitspace.setOnClickListener(new OnClickListener()
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v)
|
||||||
|
{
|
||||||
tryVibrate();
|
tryVibrate();
|
||||||
int amOrPm = mTimePicker.getIsCurrentlyAmOrPm();
|
int amOrPm = mTimePicker.getIsCurrentlyAmOrPm();
|
||||||
if (amOrPm == AM) {
|
if (amOrPm == AM) {
|
||||||
amOrPm = PM;
|
amOrPm = PM;
|
||||||
} else if (amOrPm == PM){
|
} else if (amOrPm == PM) {
|
||||||
amOrPm = AM;
|
amOrPm = AM;
|
||||||
}
|
}
|
||||||
updateAmPmDisplay(amOrPm);
|
updateAmPmDisplay(amOrPm);
|
||||||
@@ -328,56 +362,61 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
mTypedTimes = new ArrayList<Integer>();
|
mTypedTimes = new ArrayList<Integer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the theme at the end so that the initialize()s above don't counteract the theme.
|
|
||||||
mTimePicker.setTheme(getActivity().getApplicationContext(), mThemeDark);
|
|
||||||
// Prepare some palette to use.
|
|
||||||
int white = res.getColor(R.color.white);
|
|
||||||
int circleBackground = res.getColor(R.color.circle_background);
|
|
||||||
int line = res.getColor(R.color.line_background);
|
|
||||||
int timeDisplay = res.getColor(R.color.numbers_text_color);
|
|
||||||
ColorStateList doneTextColor = res.getColorStateList(R.color.done_text_color);
|
|
||||||
int doneBackground = R.drawable.done_background_color;
|
|
||||||
|
|
||||||
int darkGray = res.getColor(R.color.dark_gray);
|
// // Set the theme at the end so that the initialize()s above don't counteract the theme.
|
||||||
int lightGray = res.getColor(R.color.light_gray);
|
// mTimePicker.setTheme(getActivity().getApplicationContext(), mThemeDark);
|
||||||
int darkLine = res.getColor(R.color.line_dark);
|
// // Prepare some palette to use.
|
||||||
ColorStateList darkDoneTextColor = res.getColorStateList(R.color.done_text_color_dark);
|
// int white = res.getColor(R.color.white);
|
||||||
int darkDoneBackground = R.drawable.done_background_color_dark;
|
// int circleBackground = res.getColor(R.color.circle_background);
|
||||||
|
// int line = res.getColor(R.color.line_background);
|
||||||
|
// int timeDisplay = res.getColor(R.color.numbers_text_color);
|
||||||
|
// ColorStateList doneTextColor = res.getColorStateList(R.color.done_text_color);
|
||||||
|
// int doneBackground = R.drawable.done_background_color;
|
||||||
|
//
|
||||||
|
// int darkGray = res.getColor(R.color.dark_gray);
|
||||||
|
// int lightGray = res.getColor(R.color.light_gray);
|
||||||
|
// int darkLine = res.getColor(R.color.line_dark);
|
||||||
|
// ColorStateList darkDoneTextColor = res.getColorStateList(R.color.done_text_color_dark);
|
||||||
|
// int darkDoneBackground = R.drawable.done_background_color_dark;
|
||||||
|
|
||||||
// Set the palette for each view based on the theme.
|
// Set the palette for each view based on the theme.
|
||||||
view.findViewById(R.id.time_display_background).setBackgroundColor(mThemeDark? darkGray : white);
|
// view.findViewById(R.id.time_display_background).setBackgroundColor(mThemeDark? darkGray : white);
|
||||||
view.findViewById(R.id.time_display).setBackgroundColor(mThemeDark? darkGray : white);
|
// view.findViewById(R.id.time_display).setBackgroundColor(mThemeDark? darkGray : white);
|
||||||
((TextView) view.findViewById(R.id.separator)).setTextColor(mThemeDark? white : timeDisplay);
|
// ((TextView) view.findViewById(R.id.separator)).setTextColor(mThemeDark? white : timeDisplay);
|
||||||
((TextView) view.findViewById(R.id.ampm_label)).setTextColor(mThemeDark? white : timeDisplay);
|
// ((TextView) view.findViewById(R.id.ampm_label)).setTextColor(mThemeDark? white : timeDisplay);
|
||||||
view.findViewById(R.id.line).setBackgroundColor(mThemeDark? darkLine : line);
|
// view.findViewById(R.id.line).setBackgroundColor(mThemeDark? darkLine : line);
|
||||||
mDoneButton.setTextColor(mThemeDark? darkDoneTextColor : doneTextColor);
|
// mDoneButton.setTextColor(mThemeDark? darkDoneTextColor : doneTextColor);
|
||||||
mTimePicker.setBackgroundColor(mThemeDark? lightGray : circleBackground);
|
// mTimePicker.setBackgroundColor(mThemeDark? lightGray : circleBackground);
|
||||||
mDoneButton.setBackgroundResource(mThemeDark? darkDoneBackground : doneBackground);
|
// mDoneButton.setBackgroundResource(mThemeDark? darkDoneBackground : doneBackground);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume()
|
||||||
|
{
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mHapticFeedbackController.start();
|
mHapticFeedbackController.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause()
|
||||||
|
{
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mHapticFeedbackController.stop();
|
mHapticFeedbackController.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tryVibrate() {
|
public void tryVibrate()
|
||||||
|
{
|
||||||
mHapticFeedbackController.tryVibrate();
|
mHapticFeedbackController.tryVibrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAmPmDisplay(int amOrPm) {
|
private void updateAmPmDisplay(int amOrPm)
|
||||||
|
{
|
||||||
if (amOrPm == AM) {
|
if (amOrPm == AM) {
|
||||||
mAmPmTextView.setText(mAmText);
|
mAmPmTextView.setText(mAmText);
|
||||||
Utils.tryAccessibilityAnnounce(mTimePicker, mAmText);
|
Utils.tryAccessibilityAnnounce(mTimePicker, mAmText);
|
||||||
mAmPmHitspace.setContentDescription(mAmText);
|
mAmPmHitspace.setContentDescription(mAmText);
|
||||||
} else if (amOrPm == PM){
|
} else if (amOrPm == PM) {
|
||||||
mAmPmTextView.setText(mPmText);
|
mAmPmTextView.setText(mPmText);
|
||||||
Utils.tryAccessibilityAnnounce(mTimePicker, mPmText);
|
Utils.tryAccessibilityAnnounce(mTimePicker, mPmText);
|
||||||
mAmPmHitspace.setContentDescription(mPmText);
|
mAmPmHitspace.setContentDescription(mPmText);
|
||||||
@@ -387,7 +426,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState)
|
||||||
|
{
|
||||||
if (mTimePicker != null) {
|
if (mTimePicker != null) {
|
||||||
outState.putInt(KEY_HOUR_OF_DAY, mTimePicker.getHours());
|
outState.putInt(KEY_HOUR_OF_DAY, mTimePicker.getHours());
|
||||||
outState.putInt(KEY_MINUTE, mTimePicker.getMinutes());
|
outState.putInt(KEY_MINUTE, mTimePicker.getMinutes());
|
||||||
@@ -398,6 +438,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
outState.putIntegerArrayList(KEY_TYPED_TIMES, mTypedTimes);
|
outState.putIntegerArrayList(KEY_TYPED_TIMES, mTypedTimes);
|
||||||
}
|
}
|
||||||
outState.putBoolean(KEY_DARK_THEME, mThemeDark);
|
outState.putBoolean(KEY_DARK_THEME, mThemeDark);
|
||||||
|
outState.putInt(KEY_SELECTED_COLOR, mSelectedColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +446,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
* Called by the picker for updating the header display.
|
* Called by the picker for updating the header display.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
|
public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance)
|
||||||
|
{
|
||||||
if (pickerIndex == HOUR_INDEX) {
|
if (pickerIndex == HOUR_INDEX) {
|
||||||
setHour(newValue, false);
|
setHour(newValue, false);
|
||||||
String announcement = String.format("%d", newValue);
|
String announcement = String.format("%d", newValue);
|
||||||
@@ -417,7 +459,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
|
|
||||||
Utils.tryAccessibilityAnnounce(mTimePicker, announcement);
|
Utils.tryAccessibilityAnnounce(mTimePicker, announcement);
|
||||||
} else if (pickerIndex == MINUTE_INDEX){
|
} else if (pickerIndex == MINUTE_INDEX) {
|
||||||
setMinute(newValue);
|
setMinute(newValue);
|
||||||
mTimePicker.setContentDescription(mMinutePickerDescription + ": " + newValue);
|
mTimePicker.setContentDescription(mMinutePickerDescription + ": " + newValue);
|
||||||
} else if (pickerIndex == AMPM_INDEX) {
|
} else if (pickerIndex == AMPM_INDEX) {
|
||||||
@@ -430,7 +472,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setHour(int value, boolean announce) {
|
private void setHour(int value, boolean announce)
|
||||||
|
{
|
||||||
String format;
|
String format;
|
||||||
if (mIs24HourMode) {
|
if (mIs24HourMode) {
|
||||||
format = "%02d";
|
format = "%02d";
|
||||||
@@ -450,7 +493,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMinute(int value) {
|
private void setMinute(int value)
|
||||||
|
{
|
||||||
if (value == 60) {
|
if (value == 60) {
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
@@ -462,7 +506,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
|
|
||||||
// Show either Hours or Minutes.
|
// Show either Hours or Minutes.
|
||||||
private void setCurrentItemShowing(int index, boolean animateCircle, boolean delayLabelAnimate,
|
private void setCurrentItemShowing(int index, boolean animateCircle, boolean delayLabelAnimate,
|
||||||
boolean announce) {
|
boolean announce)
|
||||||
|
{
|
||||||
mTimePicker.setCurrentItemShowing(index, animateCircle);
|
mTimePicker.setCurrentItemShowing(index, animateCircle);
|
||||||
|
|
||||||
TextView labelToAnimate;
|
TextView labelToAnimate;
|
||||||
@@ -485,8 +530,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
labelToAnimate = mMinuteView;
|
labelToAnimate = mMinuteView;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hourColor = (index == HOUR_INDEX)? mSelectedColor : mUnselectedColor;
|
int hourColor = (index == HOUR_INDEX) ? mSelectedColor : mUnselectedColor;
|
||||||
int minuteColor = (index == MINUTE_INDEX)? mSelectedColor : mUnselectedColor;
|
int minuteColor = (index == MINUTE_INDEX) ? mSelectedColor : mUnselectedColor;
|
||||||
mHourView.setTextColor(hourColor);
|
mHourView.setTextColor(hourColor);
|
||||||
mMinuteView.setTextColor(minuteColor);
|
mMinuteView.setTextColor(minuteColor);
|
||||||
|
|
||||||
@@ -499,15 +544,17 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* For keyboard mode, processes key events.
|
* For keyboard mode, processes key events.
|
||||||
|
*
|
||||||
* @param keyCode the pressed key.
|
* @param keyCode the pressed key.
|
||||||
* @return true if the key was successfully processed, false otherwise.
|
* @return true if the key was successfully processed, false otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean processKeyUp(int keyCode) {
|
private boolean processKeyUp(int keyCode)
|
||||||
|
{
|
||||||
if (keyCode == KeyEvent.KEYCODE_ESCAPE || keyCode == KeyEvent.KEYCODE_BACK) {
|
if (keyCode == KeyEvent.KEYCODE_ESCAPE || keyCode == KeyEvent.KEYCODE_BACK) {
|
||||||
dismiss();
|
dismiss();
|
||||||
return true;
|
return true;
|
||||||
} else if (keyCode == KeyEvent.KEYCODE_TAB) {
|
} else if (keyCode == KeyEvent.KEYCODE_TAB) {
|
||||||
if(mInKbMode) {
|
if (mInKbMode) {
|
||||||
if (isTypedTimeFullyLegal()) {
|
if (isTypedTimeFullyLegal()) {
|
||||||
finishKbMode(true);
|
finishKbMode(true);
|
||||||
}
|
}
|
||||||
@@ -572,11 +619,13 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
/**
|
/**
|
||||||
* Try to start keyboard mode with the specified key, as long as the timepicker is not in the
|
* Try to start keyboard mode with the specified key, as long as the timepicker is not in the
|
||||||
* middle of a touch-event.
|
* middle of a touch-event.
|
||||||
|
*
|
||||||
* @param keyCode The key to use as the first press. Keyboard mode will not be started if the
|
* @param keyCode The key to use as the first press. Keyboard mode will not be started if the
|
||||||
* key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting
|
* key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting
|
||||||
* key.
|
* key.
|
||||||
*/
|
*/
|
||||||
private void tryStartingKbMode(int keyCode) {
|
private void tryStartingKbMode(int keyCode)
|
||||||
|
{
|
||||||
if (mTimePicker.trySettingInputEnabled(false) &&
|
if (mTimePicker.trySettingInputEnabled(false) &&
|
||||||
(keyCode == -1 || addKeyIfLegal(keyCode))) {
|
(keyCode == -1 || addKeyIfLegal(keyCode))) {
|
||||||
mInKbMode = true;
|
mInKbMode = true;
|
||||||
@@ -585,7 +634,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addKeyIfLegal(int keyCode) {
|
private boolean addKeyIfLegal(int keyCode)
|
||||||
|
{
|
||||||
// If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode,
|
// If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode,
|
||||||
// we'll need to see if AM/PM have been typed.
|
// we'll need to see if AM/PM have been typed.
|
||||||
if ((mIs24HourMode && mTypedTimes.size() == 4) ||
|
if ((mIs24HourMode && mTypedTimes.size() == 4) ||
|
||||||
@@ -617,7 +667,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
* Traverse the tree to see if the keys that have been typed so far are legal as is,
|
* Traverse the tree to see if the keys that have been typed so far are legal as is,
|
||||||
* or may become legal as more keys are typed (excluding backspace).
|
* or may become legal as more keys are typed (excluding backspace).
|
||||||
*/
|
*/
|
||||||
private boolean isTypedTimeLegalSoFar() {
|
private boolean isTypedTimeLegalSoFar()
|
||||||
|
{
|
||||||
Node node = mLegalTimesTree;
|
Node node = mLegalTimesTree;
|
||||||
for (int keyCode : mTypedTimes) {
|
for (int keyCode : mTypedTimes) {
|
||||||
node = node.canReach(keyCode);
|
node = node.canReach(keyCode);
|
||||||
@@ -631,7 +682,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
/**
|
/**
|
||||||
* Check if the time that has been typed so far is completely legal, as is.
|
* Check if the time that has been typed so far is completely legal, as is.
|
||||||
*/
|
*/
|
||||||
private boolean isTypedTimeFullyLegal() {
|
private boolean isTypedTimeFullyLegal()
|
||||||
|
{
|
||||||
if (mIs24HourMode) {
|
if (mIs24HourMode) {
|
||||||
// For 24-hour mode, the time is legal if the hours and minutes are each legal. Note:
|
// For 24-hour mode, the time is legal if the hours and minutes are each legal. Note:
|
||||||
// getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode.
|
// getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode.
|
||||||
@@ -645,7 +697,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int deleteLastTypedKey() {
|
private int deleteLastTypedKey()
|
||||||
|
{
|
||||||
int deleted = mTypedTimes.remove(mTypedTimes.size() - 1);
|
int deleted = mTypedTimes.remove(mTypedTimes.size() - 1);
|
||||||
if (!isTypedTimeFullyLegal()) {
|
if (!isTypedTimeFullyLegal()) {
|
||||||
mDoneButton.setEnabled(false);
|
mDoneButton.setEnabled(false);
|
||||||
@@ -655,9 +708,11 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
|
* Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
|
||||||
|
*
|
||||||
* @param changeDisplays If true, update the displays with the relevant time.
|
* @param changeDisplays If true, update the displays with the relevant time.
|
||||||
*/
|
*/
|
||||||
private void finishKbMode(boolean updateDisplays) {
|
private void finishKbMode(boolean updateDisplays)
|
||||||
|
{
|
||||||
mInKbMode = false;
|
mInKbMode = false;
|
||||||
if (!mTypedTimes.isEmpty()) {
|
if (!mTypedTimes.isEmpty()) {
|
||||||
int values[] = getEnteredTime(null);
|
int values[] = getEnteredTime(null);
|
||||||
@@ -677,28 +732,30 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
* Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is
|
* Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is
|
||||||
* empty, either show an empty display (filled with the placeholder text), or update from the
|
* empty, either show an empty display (filled with the placeholder text), or update from the
|
||||||
* timepicker's values.
|
* timepicker's values.
|
||||||
|
*
|
||||||
* @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text.
|
* @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text.
|
||||||
* Otherwise, revert to the timepicker's values.
|
* Otherwise, revert to the timepicker's values.
|
||||||
*/
|
*/
|
||||||
private void updateDisplay(boolean allowEmptyDisplay) {
|
private void updateDisplay(boolean allowEmptyDisplay)
|
||||||
|
{
|
||||||
if (!allowEmptyDisplay && mTypedTimes.isEmpty()) {
|
if (!allowEmptyDisplay && mTypedTimes.isEmpty()) {
|
||||||
int hour = mTimePicker.getHours();
|
int hour = mTimePicker.getHours();
|
||||||
int minute = mTimePicker.getMinutes();
|
int minute = mTimePicker.getMinutes();
|
||||||
setHour(hour, true);
|
setHour(hour, true);
|
||||||
setMinute(minute);
|
setMinute(minute);
|
||||||
if (!mIs24HourMode) {
|
if (!mIs24HourMode) {
|
||||||
updateAmPmDisplay(hour < 12? AM : PM);
|
updateAmPmDisplay(hour < 12 ? AM : PM);
|
||||||
}
|
}
|
||||||
setCurrentItemShowing(mTimePicker.getCurrentItemShowing(), true, true, true);
|
setCurrentItemShowing(mTimePicker.getCurrentItemShowing(), true, true, true);
|
||||||
mDoneButton.setEnabled(true);
|
mDoneButton.setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
Boolean[] enteredZeros = {false, false};
|
Boolean[] enteredZeros = {false, false};
|
||||||
int[] values = getEnteredTime(enteredZeros);
|
int[] values = getEnteredTime(enteredZeros);
|
||||||
String hourFormat = enteredZeros[0]? "%02d" : "%2d";
|
String hourFormat = enteredZeros[0] ? "%02d" : "%2d";
|
||||||
String minuteFormat = (enteredZeros[1])? "%02d" : "%2d";
|
String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d";
|
||||||
String hourStr = (values[0] == -1)? mDoublePlaceholderText :
|
String hourStr = (values[0] == -1) ? mDoublePlaceholderText :
|
||||||
String.format(hourFormat, values[0]).replace(' ', mPlaceholderText);
|
String.format(hourFormat, values[0]).replace(' ', mPlaceholderText);
|
||||||
String minuteStr = (values[1] == -1)? mDoublePlaceholderText :
|
String minuteStr = (values[1] == -1) ? mDoublePlaceholderText :
|
||||||
String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText);
|
String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText);
|
||||||
mHourView.setText(hourStr);
|
mHourView.setText(hourStr);
|
||||||
mHourSpaceView.setText(hourStr);
|
mHourSpaceView.setText(hourStr);
|
||||||
@@ -712,7 +769,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getValFromKeyCode(int keyCode) {
|
private static int getValFromKeyCode(int keyCode)
|
||||||
|
{
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_0:
|
case KeyEvent.KEYCODE_0:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -741,20 +799,22 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the currently-entered time, as integer values of the hours and minutes typed.
|
* Get the currently-entered time, as integer values of the hours and minutes typed.
|
||||||
|
*
|
||||||
* @param enteredZeros A size-2 boolean array, which the caller should initialize, and which
|
* @param enteredZeros A size-2 boolean array, which the caller should initialize, and which
|
||||||
* may then be used for the caller to know whether zeros had been explicitly entered as either
|
* may then be used for the caller to know whether zeros had been explicitly entered as either
|
||||||
* hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's.
|
* hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's.
|
||||||
* @return A size-3 int array. The first value will be the hours, the second value will be the
|
* @return A size-3 int array. The first value will be the hours, the second value will be the
|
||||||
* minutes, and the third will be either TimePickerDialog.AM or TimePickerDialog.PM.
|
* minutes, and the third will be either TimePickerDialog.AM or TimePickerDialog.PM.
|
||||||
*/
|
*/
|
||||||
private int[] getEnteredTime(Boolean[] enteredZeros) {
|
private int[] getEnteredTime(Boolean[] enteredZeros)
|
||||||
|
{
|
||||||
int amOrPm = -1;
|
int amOrPm = -1;
|
||||||
int startIndex = 1;
|
int startIndex = 1;
|
||||||
if (!mIs24HourMode && isTypedTimeFullyLegal()) {
|
if (!mIs24HourMode && isTypedTimeFullyLegal()) {
|
||||||
int keyCode = mTypedTimes.get(mTypedTimes.size() - 1);
|
int keyCode = mTypedTimes.get(mTypedTimes.size() - 1);
|
||||||
if (keyCode == getAmOrPmKeyCode(AM)) {
|
if (keyCode == getAmOrPmKeyCode(AM)) {
|
||||||
amOrPm = AM;
|
amOrPm = AM;
|
||||||
} else if (keyCode == getAmOrPmKeyCode(PM)){
|
} else if (keyCode == getAmOrPmKeyCode(PM)) {
|
||||||
amOrPm = PM;
|
amOrPm = PM;
|
||||||
}
|
}
|
||||||
startIndex = 2;
|
startIndex = 2;
|
||||||
@@ -765,15 +825,15 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i));
|
int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i));
|
||||||
if (i == startIndex) {
|
if (i == startIndex) {
|
||||||
minute = val;
|
minute = val;
|
||||||
} else if (i == startIndex+1) {
|
} else if (i == startIndex + 1) {
|
||||||
minute += 10*val;
|
minute += 10 * val;
|
||||||
if (enteredZeros != null && val == 0) {
|
if (enteredZeros != null && val == 0) {
|
||||||
enteredZeros[1] = true;
|
enteredZeros[1] = true;
|
||||||
}
|
}
|
||||||
} else if (i == startIndex+2) {
|
} else if (i == startIndex + 2) {
|
||||||
hour = val;
|
hour = val;
|
||||||
} else if (i == startIndex+3) {
|
} else if (i == startIndex + 3) {
|
||||||
hour += 10*val;
|
hour += 10 * val;
|
||||||
if (enteredZeros != null && val == 0) {
|
if (enteredZeros != null && val == 0) {
|
||||||
enteredZeros[0] = true;
|
enteredZeros[0] = true;
|
||||||
}
|
}
|
||||||
@@ -787,7 +847,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
/**
|
/**
|
||||||
* Get the keycode value for AM and PM in the current language.
|
* Get the keycode value for AM and PM in the current language.
|
||||||
*/
|
*/
|
||||||
private int getAmOrPmKeyCode(int amOrPm) {
|
private int getAmOrPmKeyCode(int amOrPm)
|
||||||
|
{
|
||||||
// Cache the codes.
|
// Cache the codes.
|
||||||
if (mAmKeyCode == -1 || mPmKeyCode == -1) {
|
if (mAmKeyCode == -1 || mPmKeyCode == -1) {
|
||||||
// Find the first character in the AM/PM text that is unique.
|
// Find the first character in the AM/PM text that is unique.
|
||||||
@@ -822,7 +883,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
/**
|
/**
|
||||||
* Create a tree for deciding what keys can legally be typed.
|
* Create a tree for deciding what keys can legally be typed.
|
||||||
*/
|
*/
|
||||||
private void generateLegalTimesTree() {
|
private void generateLegalTimesTree()
|
||||||
|
{
|
||||||
// Create a quick cache of numbers to their keycodes.
|
// Create a quick cache of numbers to their keycodes.
|
||||||
int k0 = KeyEvent.KEYCODE_0;
|
int k0 = KeyEvent.KEYCODE_0;
|
||||||
int k1 = KeyEvent.KEYCODE_1;
|
int k1 = KeyEvent.KEYCODE_1;
|
||||||
@@ -955,20 +1017,24 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
* mLegalKeys represents the keys that can be typed to get to the node.
|
* mLegalKeys represents the keys that can be typed to get to the node.
|
||||||
* mChildren are the children that can be reached from this node.
|
* mChildren are the children that can be reached from this node.
|
||||||
*/
|
*/
|
||||||
private class Node {
|
private class Node
|
||||||
|
{
|
||||||
private int[] mLegalKeys;
|
private int[] mLegalKeys;
|
||||||
private ArrayList<Node> mChildren;
|
private ArrayList<Node> mChildren;
|
||||||
|
|
||||||
public Node(int... legalKeys) {
|
public Node(int... legalKeys)
|
||||||
|
{
|
||||||
mLegalKeys = legalKeys;
|
mLegalKeys = legalKeys;
|
||||||
mChildren = new ArrayList<Node>();
|
mChildren = new ArrayList<Node>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addChild(Node child) {
|
public void addChild(Node child)
|
||||||
|
{
|
||||||
mChildren.add(child);
|
mChildren.add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(int key) {
|
public boolean containsKey(int key)
|
||||||
|
{
|
||||||
for (int i = 0; i < mLegalKeys.length; i++) {
|
for (int i = 0; i < mLegalKeys.length; i++) {
|
||||||
if (mLegalKeys[i] == key) {
|
if (mLegalKeys[i] == key) {
|
||||||
return true;
|
return true;
|
||||||
@@ -977,7 +1043,8 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node canReach(int key) {
|
public Node canReach(int key)
|
||||||
|
{
|
||||||
if (mChildren == null) {
|
if (mChildren == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -990,9 +1057,11 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class KeyboardListener implements OnKeyListener {
|
private class KeyboardListener implements OnKeyListener
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
public boolean onKey(View v, int keyCode, KeyEvent event)
|
||||||
|
{
|
||||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
return processKeyUp(keyCode);
|
return processKeyUp(keyCode);
|
||||||
}
|
}
|
||||||
@@ -1000,14 +1069,16 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDismissListener( DialogInterface.OnDismissListener listener ) {
|
public void setDismissListener(DialogInterface.OnDismissListener listener)
|
||||||
|
{
|
||||||
dismissListener = listener;
|
dismissListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDismiss(DialogInterface dialog) {
|
public void onDismiss(DialogInterface dialog)
|
||||||
|
{
|
||||||
super.onDismiss(dialog);
|
super.onDismiss(dialog);
|
||||||
if( dismissListener != null )
|
if (dismissListener != null)
|
||||||
dismissListener.onDismiss(dialog);
|
dismissListener.onDismiss(dialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,33 +49,33 @@
|
|||||||
android:layout_height="1dip"
|
android:layout_height="1dip"
|
||||||
android:background="@color/line_background" />
|
android:background="@color/line_background" />
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
style="?android:attr/buttonBarStyle"
|
style="?android:attr/buttonBarStyle"
|
||||||
android:layout_width="@dimen/date_picker_component_width"
|
android:layout_width="@dimen/date_picker_component_width"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
android:id="@+id/clear_button"
|
android:id="@+id/clear_button"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/done_background_color"
|
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
|
android:textColor="#333"
|
||||||
android:text="@string/clear_label"
|
android:text="@string/clear_label"
|
||||||
android:textColor="@color/done_text_color"
|
|
||||||
android:textSize="@dimen/done_label_size" />
|
android:textSize="@dimen/done_label_size" />
|
||||||
|
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
android:id="@+id/done_button"
|
android:id="@+id/done_button"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/done_background_color"
|
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
|
android:textColor="#333"
|
||||||
android:text="@string/done_label"
|
android:text="@string/done_label"
|
||||||
android:textColor="@color/done_text_color"
|
|
||||||
android:textSize="@dimen/done_label_size" />
|
android:textSize="@dimen/done_label_size" />
|
||||||
</LinearLayout>
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -76,7 +76,7 @@ build_apk() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
log_info "Building debug APK"
|
log_info "Building debug APK"
|
||||||
./gradlew assembleDebug || fail
|
./gradlew assembleDebug --stacktrace || fail
|
||||||
cp -v uhabits-android/build/outputs/apk/debug/uhabits-android-debug.apk build/loop-$VERSION-debug.apk
|
cp -v uhabits-android/build/outputs/apk/debug/uhabits-android-debug.apk build/loop-$VERSION-debug.apk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ plugins {
|
|||||||
id 'kotlin-android'
|
id 'kotlin-android'
|
||||||
id 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
id 'com.github.triplet.play' version '2.6.2'
|
id 'com.github.triplet.play' version '2.6.2'
|
||||||
|
id 'kotlin-android-extensions'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -69,6 +70,10 @@ android {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
main.assets.srcDirs += '../uhabits-core/src/main/resources/'
|
main.assets.srcDirs += '../uhabits-core/src/main/resources/'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -89,6 +94,7 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4"
|
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4"
|
||||||
|
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
compileOnly "javax.annotation:jsr250-api:1.0"
|
compileOnly "javax.annotation:jsr250-api:1.0"
|
||||||
compileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
|
compileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
|
||||||
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
|
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
|
||||||
|
|||||||
@@ -54,12 +54,15 @@ public class HabitsTest extends BaseUserInterfaceTest
|
|||||||
verifyShowsScreen(LIST_HABITS);
|
verifyShowsScreen(LIST_HABITS);
|
||||||
clickMenu(ADD);
|
clickMenu(ADD);
|
||||||
|
|
||||||
|
verifyShowsScreen(SELECT_HABIT_TYPE);
|
||||||
|
clickText("Yes or No");
|
||||||
|
|
||||||
verifyShowsScreen(EDIT_HABIT);
|
verifyShowsScreen(EDIT_HABIT);
|
||||||
String testName = "Hello world";
|
String testName = "Hello world";
|
||||||
typeName(testName);
|
typeName(testName);
|
||||||
typeQuestion("Did you say hello to the world today?");
|
typeQuestion("Did you say hello to the world today?");
|
||||||
typeDescription(description);
|
typeDescription(description);
|
||||||
pickFrequency("Every week");
|
pickFrequency();
|
||||||
pickColor(5);
|
pickColor(5);
|
||||||
clickSave();
|
clickSave();
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ public class CommonSteps extends BaseUserInterfaceTest
|
|||||||
|
|
||||||
public enum Screen
|
public enum Screen
|
||||||
{
|
{
|
||||||
LIST_HABITS, SHOW_HABIT, EDIT_HABIT
|
LIST_HABITS, SHOW_HABIT, EDIT_HABIT, SELECT_HABIT_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void verifyShowsScreen(Screen screen) {
|
public static void verifyShowsScreen(Screen screen) {
|
||||||
@@ -176,9 +176,15 @@ public class CommonSteps extends BaseUserInterfaceTest
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EDIT_HABIT:
|
case EDIT_HABIT:
|
||||||
onView(withId(R.id.tvQuestion)).check(matches(isDisplayed()));
|
onView(withId(R.id.questionInput)).check(matches(isDisplayed()));
|
||||||
onView(withId(R.id.tvDescription)).check(matches(isDisplayed()));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SELECT_HABIT_TYPE:
|
||||||
|
onView(withText(R.string.yes_or_no_example)).check(matches(isDisplayed()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,42 +36,42 @@ public class EditHabitSteps
|
|||||||
onView(withId(R.id.buttonSave)).perform(click());
|
onView(withId(R.id.buttonSave)).perform(click());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pickFrequency(String freq)
|
public static void pickFrequency()
|
||||||
{
|
{
|
||||||
onView(withId(R.id.spinner)).perform(click());
|
onView(withId(R.id.frequencyPicker)).perform(click());
|
||||||
device.findObject(By.text(freq)).click();
|
onView(withText("SAVE")).perform(click());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pickColor(int color)
|
public static void pickColor(int color)
|
||||||
{
|
{
|
||||||
onView(withId(R.id.buttonPickColor)).perform(click());
|
onView(withId(R.id.colorButton)).perform(click());
|
||||||
device.findObject(By.descStartsWith(String.format("Color %d", color))).click();
|
device.findObject(By.descStartsWith(String.format("Color %d", color))).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void typeName(String name)
|
public static void typeName(String name)
|
||||||
{
|
{
|
||||||
typeTextWithId(R.id.tvName, name);
|
typeTextWithId(R.id.nameInput, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void typeQuestion(String name)
|
public static void typeQuestion(String name)
|
||||||
{
|
{
|
||||||
typeTextWithId(R.id.tvQuestion, name);
|
typeTextWithId(R.id.questionInput, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void typeDescription(String description)
|
public static void typeDescription(String description)
|
||||||
{
|
{
|
||||||
typeTextWithId(R.id.tvDescription, description);
|
typeTextWithId(R.id.notesInput, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setReminder()
|
public static void setReminder()
|
||||||
{
|
{
|
||||||
onView(withId(R.id.tvReminderTime)).perform(click());
|
onView(withId(R.id.reminderTimePicker)).perform(click());
|
||||||
onView(withId(R.id.done_button)).perform(click());
|
onView(withId(R.id.done_button)).perform(click());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clickReminderDays()
|
public static void clickReminderDays()
|
||||||
{
|
{
|
||||||
onView(withId(R.id.tvReminderDays)).perform(click());
|
onView(withId(R.id.reminderDatePicker)).perform(click());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unselectAllDays()
|
public static void unselectAllDays()
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public abstract class ListHabitsSteps
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ADD:
|
case ADD:
|
||||||
clickViewWithId(R.id.actionCreateBooleanHabit);
|
clickViewWithId(R.id.actionCreateHabit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EDIT:
|
case EDIT:
|
||||||
|
|||||||
@@ -1,32 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
package="org.isoron.uhabits">
|
||||||
~
|
|
||||||
~ This file is part of Loop Habit Tracker.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by the
|
|
||||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
~ option) any later version.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
~ more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License along
|
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
<manifest
|
|
||||||
package="org.isoron.uhabits"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
@@ -37,15 +15,24 @@
|
|||||||
android:label="@string/main_activity_title"
|
android:label="@string/main_activity_title"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppBaseTheme">
|
android:theme="@style/AppBaseTheme">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:exported="true"
|
||||||
|
android:name=".activities.habits.edit.EditHabitActivity">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.backup.api_key"
|
android:name="com.google.android.backup.api_key"
|
||||||
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw"/>
|
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.habits.list.ListHabitsActivity"
|
android:name=".activities.habits.list.ListHabitsActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/main_activity_title"
|
android:label="@string/main_activity_title"
|
||||||
android:launchMode="singleTop"/>
|
android:launchMode="singleTop" />
|
||||||
|
|
||||||
<activity-alias
|
<activity-alias
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@@ -53,8 +40,9 @@
|
|||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
||||||
<intent-filter android:label="@string/main_activity_title">
|
<intent-filter android:label="@string/main_activity_title">
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
@@ -63,24 +51,24 @@
|
|||||||
android:label="@string/title_activity_show_habit">
|
android:label="@string/title_activity_show_habit">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.settings.SettingsActivity"
|
android:name=".activities.settings.SettingsActivity"
|
||||||
android:label="@string/settings">
|
android:label="@string/settings">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.intro.IntroActivity"
|
android:name=".activities.intro.IntroActivity"
|
||||||
android:label=""
|
android:label=""
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".widgets.HabitPickerDialog"
|
android:name=".widgets.HabitPickerDialog"
|
||||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
@@ -88,124 +76,123 @@
|
|||||||
android:label="@string/about">
|
android:label="@string/about">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".notifications.SnoozeDelayPickerActivity"
|
<activity
|
||||||
|
android:name=".notifications.SnoozeDelayPickerActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.CheckmarkWidgetProvider"
|
android:name=".widgets.CheckmarkWidgetProvider"
|
||||||
android:label="@string/checkmark">
|
android:label="@string/checkmark">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_checkmark_info"/>
|
android:resource="@xml/widget_checkmark_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<service android:name=".widgets.StackWidgetService"
|
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS"
|
<service
|
||||||
android:exported="false" />
|
android:name=".widgets.StackWidgetService"
|
||||||
|
android:exported="false"
|
||||||
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.HistoryWidgetProvider"
|
android:name=".widgets.HistoryWidgetProvider"
|
||||||
android:label="@string/history">
|
android:label="@string/history">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_history_info"/>
|
android:resource="@xml/widget_history_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.ScoreWidgetProvider"
|
android:name=".widgets.ScoreWidgetProvider"
|
||||||
android:label="@string/habit_strength">
|
android:label="@string/habit_strength">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_score_info"/>
|
android:resource="@xml/widget_score_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.StreakWidgetProvider"
|
android:name=".widgets.StreakWidgetProvider"
|
||||||
android:label="@string/streaks">
|
android:label="@string/streaks">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_streak_info"/>
|
android:resource="@xml/widget_streak_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.FrequencyWidgetProvider"
|
android:name=".widgets.FrequencyWidgetProvider"
|
||||||
android:label="@string/frequency">
|
android:label="@string/frequency">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_frequency_info"/>
|
android:resource="@xml/widget_frequency_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".receivers.ReminderReceiver">
|
<receiver android:name=".receivers.ReminderReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".receivers.WidgetReceiver">
|
<receiver android:name=".receivers.WidgetReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION"/>
|
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION" />
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="org.isoron.uhabits"
|
android:host="org.isoron.uhabits"
|
||||||
android:scheme="content"/>
|
android:scheme="content" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<action android:name="org.isoron.uhabits.ACTION_ADD_REPETITION"/>
|
<action android:name="org.isoron.uhabits.ACTION_ADD_REPETITION" />
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="org.isoron.uhabits"
|
android:host="org.isoron.uhabits"
|
||||||
android:scheme="content"/>
|
android:scheme="content" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<action android:name="org.isoron.uhabits.ACTION_REMOVE_REPETITION"/>
|
<action android:name="org.isoron.uhabits.ACTION_REMOVE_REPETITION" />
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="org.isoron.uhabits"
|
android:host="org.isoron.uhabits"
|
||||||
android:scheme="content"/>
|
android:scheme="content" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver> <!-- Locale/Tasker -->
|
||||||
|
|
||||||
<!-- Locale/Tasker -->
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".automation.EditSettingActivity"
|
android:name=".automation.EditSettingActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING"/>
|
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity> <!-- Locale/Tasker -->
|
||||||
|
|
||||||
<!-- Locale/Tasker -->
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".automation.FireSettingReceiver"
|
android:name=".automation.FireSettingReceiver"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING"/>
|
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
@@ -216,14 +203,13 @@
|
|||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/file_paths"/>
|
android:resource="@xml/file_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".sync.SyncService"
|
android:name=".sync.SyncService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false">
|
android:exported="false"></service>
|
||||||
</service>
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities
|
package org.isoron.uhabits.activities
|
||||||
|
|
||||||
|
import android.app.*
|
||||||
import android.content.res.Configuration.*
|
import android.content.res.Configuration.*
|
||||||
import android.os.Build.VERSION.*
|
import android.os.Build.VERSION.*
|
||||||
import androidx.core.content.*
|
import androidx.core.content.*
|
||||||
@@ -30,8 +31,8 @@ import javax.inject.*
|
|||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
class AndroidThemeSwitcher
|
class AndroidThemeSwitcher
|
||||||
@Inject constructor(
|
constructor(
|
||||||
private val activity: BaseActivity,
|
private val activity: Activity,
|
||||||
preferences: Preferences
|
preferences: Preferences
|
||||||
) : ThemeSwitcher(preferences) {
|
) : ThemeSwitcher(preferences) {
|
||||||
|
|
||||||
|
|||||||
@@ -48,5 +48,5 @@ interface HabitsActivityComponent {
|
|||||||
val listHabitsScreen: ListHabitsScreen
|
val listHabitsScreen: ListHabitsScreen
|
||||||
val listHabitsSelectionMenu: ListHabitsSelectionMenu
|
val listHabitsSelectionMenu: ListHabitsSelectionMenu
|
||||||
val showHabitScreen: ShowHabitScreen
|
val showHabitScreen: ShowHabitScreen
|
||||||
val themeSwitcher: AndroidThemeSwitcher
|
val themeSwitcher: ThemeSwitcher
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,17 @@ package org.isoron.uhabits.activities
|
|||||||
|
|
||||||
import dagger.*
|
import dagger.*
|
||||||
import org.isoron.androidbase.activities.*
|
import org.isoron.androidbase.activities.*
|
||||||
|
import org.isoron.uhabits.core.preferences.*
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.ui.*
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
abstract class HabitsActivityModule {
|
class HabitsActivityModule {
|
||||||
@Binds @ActivityScope
|
|
||||||
internal abstract fun getThemeSwitcher(t: AndroidThemeSwitcher): ThemeSwitcher
|
@Provides
|
||||||
|
@ActivityScope
|
||||||
|
fun getThemeSwitcher(activity: BaseActivity,
|
||||||
|
prefs: Preferences
|
||||||
|
): ThemeSwitcher {
|
||||||
|
return AndroidThemeSwitcher(activity, prefs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.activities.common.dialogs
|
||||||
|
|
||||||
|
import android.app.*
|
||||||
|
import android.os.*
|
||||||
|
import android.util.*
|
||||||
|
import android.view.*
|
||||||
|
import android.widget.*
|
||||||
|
import androidx.appcompat.app.*
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import kotlinx.android.synthetic.main.frequency_picker_dialog.view.*
|
||||||
|
import org.isoron.uhabits.*
|
||||||
|
|
||||||
|
|
||||||
|
class FrequencyPickerDialog(var freqNumerator: Int,
|
||||||
|
var freqDenominator: Int
|
||||||
|
) : AppCompatDialogFragment() {
|
||||||
|
|
||||||
|
lateinit var contentView: View
|
||||||
|
var onFrequencyPicked: (num: Int, den: Int) -> Unit = {_,_ -> }
|
||||||
|
|
||||||
|
constructor() : this(1, 1)
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val inflater = LayoutInflater.from(activity!!)
|
||||||
|
contentView = inflater.inflate(R.layout.frequency_picker_dialog, null)
|
||||||
|
|
||||||
|
contentView.everyDayRadioButton.setOnClickListener {
|
||||||
|
check(contentView.everyDayRadioButton)
|
||||||
|
unfocusAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.everyXDaysRadioButton.setOnClickListener {
|
||||||
|
check(contentView.everyXDaysRadioButton)
|
||||||
|
val everyXDaysTextView = contentView.everyXDaysTextView
|
||||||
|
focus(everyXDaysTextView)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.everyXDaysTextView.setOnFocusChangeListener { v, hasFocus ->
|
||||||
|
if(hasFocus) check(contentView.everyXDaysRadioButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.xTimesPerWeekRadioButton.setOnClickListener {
|
||||||
|
check(contentView.xTimesPerWeekRadioButton)
|
||||||
|
focus(contentView.xTimesPerWeekTextView)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.xTimesPerWeekTextView.setOnFocusChangeListener { v, hasFocus ->
|
||||||
|
if(hasFocus) check(contentView.xTimesPerWeekRadioButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.xTimesPerMonthRadioButton.setOnClickListener {
|
||||||
|
check(contentView.xTimesPerMonthRadioButton)
|
||||||
|
focus(contentView.xTimesPerMonthTextView)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentView.xTimesPerMonthTextView.setOnFocusChangeListener { v, hasFocus ->
|
||||||
|
if(hasFocus) check(contentView.xTimesPerMonthRadioButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
return AlertDialog.Builder(activity!!)
|
||||||
|
.setView(contentView)
|
||||||
|
.setPositiveButton(R.string.save) { _, _ -> onSaveClicked() }
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onSaveClicked() {
|
||||||
|
var numerator = 1
|
||||||
|
var denominator = 1
|
||||||
|
when {
|
||||||
|
contentView.everyDayRadioButton.isChecked -> {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
contentView.everyXDaysRadioButton.isChecked -> {
|
||||||
|
if (contentView.everyXDaysTextView.text.isNotEmpty()) {
|
||||||
|
denominator = Integer.parseInt(contentView.everyXDaysTextView.text.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentView.xTimesPerWeekRadioButton.isChecked -> {
|
||||||
|
if (contentView.xTimesPerWeekTextView.text.isNotEmpty()) {
|
||||||
|
numerator = Integer.parseInt(contentView.xTimesPerWeekTextView.text.toString())
|
||||||
|
denominator = 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
if (contentView.xTimesPerMonthTextView.text.isNotEmpty()) {
|
||||||
|
numerator = Integer.parseInt(contentView.xTimesPerMonthTextView.text.toString())
|
||||||
|
denominator = 30
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numerator >= denominator || numerator < 1) {
|
||||||
|
numerator = 1
|
||||||
|
denominator = 1
|
||||||
|
}
|
||||||
|
onFrequencyPicked(numerator, denominator)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun check(view: RadioButton?) {
|
||||||
|
uncheckAll()
|
||||||
|
view?.isChecked = true
|
||||||
|
view?.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
populateViews()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateViews() {
|
||||||
|
uncheckAll()
|
||||||
|
if (freqNumerator == 1) {
|
||||||
|
if(freqDenominator == 1) {
|
||||||
|
contentView.everyDayRadioButton.isChecked = true
|
||||||
|
} else {
|
||||||
|
contentView.everyXDaysRadioButton.isChecked = true
|
||||||
|
contentView.everyXDaysTextView.setText(freqDenominator.toString())
|
||||||
|
focus(contentView.everyXDaysTextView)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(freqDenominator == 7) {
|
||||||
|
contentView.xTimesPerWeekRadioButton.isChecked = true
|
||||||
|
contentView.xTimesPerWeekTextView.setText(freqNumerator.toString())
|
||||||
|
focus(contentView.xTimesPerWeekTextView)
|
||||||
|
} else if (freqDenominator == 30 || freqDenominator == 31) {
|
||||||
|
contentView.xTimesPerMonthRadioButton.isChecked = true
|
||||||
|
contentView.xTimesPerMonthTextView.setText(freqNumerator.toString())
|
||||||
|
focus(contentView.xTimesPerMonthTextView)
|
||||||
|
} else {
|
||||||
|
Log.w("FrequencyPickerDialog", "Unknown frequency: $freqNumerator/$freqDenominator")
|
||||||
|
contentView.everyDayRadioButton.isChecked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun focus(view: EditText) {
|
||||||
|
view.requestFocus()
|
||||||
|
view.setSelection(view.text.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uncheckAll() {
|
||||||
|
contentView.everyDayRadioButton.isChecked = false
|
||||||
|
contentView.everyXDaysRadioButton.isChecked = false
|
||||||
|
contentView.xTimesPerWeekRadioButton.isChecked = false
|
||||||
|
contentView.xTimesPerMonthRadioButton.isChecked = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unfocusAll() {
|
||||||
|
contentView.everyXDaysTextView.clearFocus()
|
||||||
|
contentView.xTimesPerWeekTextView.clearFocus()
|
||||||
|
contentView.xTimesPerMonthTextView.clearFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.activities.habits.edit
|
||||||
|
|
||||||
|
import android.content.res.*
|
||||||
|
import android.graphics.*
|
||||||
|
import android.os.*
|
||||||
|
import android.text.format.*
|
||||||
|
import android.view.*
|
||||||
|
import androidx.appcompat.app.*
|
||||||
|
import androidx.fragment.app.*
|
||||||
|
import com.android.datetimepicker.time.*
|
||||||
|
import kotlinx.android.synthetic.main.activity_edit_habit.*
|
||||||
|
import org.isoron.androidbase.utils.*
|
||||||
|
import org.isoron.uhabits.*
|
||||||
|
import org.isoron.uhabits.activities.*
|
||||||
|
import org.isoron.uhabits.activities.common.dialogs.*
|
||||||
|
import org.isoron.uhabits.core.commands.*
|
||||||
|
import org.isoron.uhabits.core.models.*
|
||||||
|
import org.isoron.uhabits.databinding.*
|
||||||
|
import org.isoron.uhabits.utils.*
|
||||||
|
|
||||||
|
class EditHabitActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var themeSwitcher: AndroidThemeSwitcher
|
||||||
|
private lateinit var binding: ActivityEditHabitBinding
|
||||||
|
private lateinit var commandRunner: CommandRunner
|
||||||
|
|
||||||
|
var habitId = -1L
|
||||||
|
var paletteColor = 11
|
||||||
|
var androidColor = 0
|
||||||
|
var freqNum = 1
|
||||||
|
var freqDen = 1
|
||||||
|
var reminderHour = -1
|
||||||
|
var reminderMin = -1
|
||||||
|
var reminderDays: WeekdayList = WeekdayList.EVERY_DAY
|
||||||
|
|
||||||
|
override fun onCreate(state: Bundle?) {
|
||||||
|
super.onCreate(state)
|
||||||
|
|
||||||
|
val component = (application as HabitsApplication).component
|
||||||
|
themeSwitcher = AndroidThemeSwitcher(this, component.preferences)
|
||||||
|
themeSwitcher.apply()
|
||||||
|
|
||||||
|
binding = ActivityEditHabitBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
if (intent.hasExtra("habitId")) {
|
||||||
|
binding.toolbar.title = getString(R.string.edit_habit)
|
||||||
|
habitId = intent.getLongExtra("habitId", -1)
|
||||||
|
val habit = component.habitList.getById(habitId)!!
|
||||||
|
paletteColor = habit.color
|
||||||
|
freqNum = habit.frequency.numerator
|
||||||
|
freqDen = habit.frequency.denominator
|
||||||
|
if (habit.hasReminder()) {
|
||||||
|
reminderHour = habit.reminder.hour
|
||||||
|
reminderMin = habit.reminder.minute
|
||||||
|
reminderDays = habit.reminder.days
|
||||||
|
}
|
||||||
|
binding.nameInput.setText(habit.name)
|
||||||
|
binding.questionInput.setText(habit.question)
|
||||||
|
binding.notesInput.setText(habit.description)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != null) {
|
||||||
|
habitId = state.getLong("habitId")
|
||||||
|
paletteColor = state.getInt("paletteColor")
|
||||||
|
freqNum = state.getInt("freqNum")
|
||||||
|
freqDen = state.getInt("freqDen")
|
||||||
|
reminderHour = state.getInt("reminderHour")
|
||||||
|
reminderMin = state.getInt("reminderMin")
|
||||||
|
reminderDays = WeekdayList(state.getInt("reminderDays"))
|
||||||
|
}
|
||||||
|
|
||||||
|
updateColors()
|
||||||
|
|
||||||
|
setSupportActionBar(binding.toolbar)
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
supportActionBar?.elevation = 10.0f
|
||||||
|
|
||||||
|
val colorPickerDialogFactory = ColorPickerDialogFactory(this)
|
||||||
|
binding.colorButton.setOnClickListener {
|
||||||
|
val dialog = colorPickerDialogFactory.create(paletteColor)
|
||||||
|
dialog.setListener { paletteColor ->
|
||||||
|
this.paletteColor = paletteColor
|
||||||
|
updateColors()
|
||||||
|
}
|
||||||
|
dialog.show(supportFragmentManager, "colorPicker")
|
||||||
|
}
|
||||||
|
|
||||||
|
populateFrequency()
|
||||||
|
binding.frequencyPicker.setOnClickListener {
|
||||||
|
val dialog = FrequencyPickerDialog(freqNum, freqDen)
|
||||||
|
dialog.onFrequencyPicked = { num, den ->
|
||||||
|
freqNum = num
|
||||||
|
freqDen = den
|
||||||
|
populateFrequency()
|
||||||
|
}
|
||||||
|
dialog.show(supportFragmentManager, "frequencyPicker")
|
||||||
|
}
|
||||||
|
|
||||||
|
populateReminder()
|
||||||
|
binding.reminderTimePicker.setOnClickListener {
|
||||||
|
val currentHour = if (reminderHour >= 0) reminderHour else 8
|
||||||
|
val currentMin = if (reminderMin >= 0) reminderMin else 0
|
||||||
|
val is24HourMode = DateFormat.is24HourFormat(this)
|
||||||
|
val dialog = TimePickerDialog.newInstance(object : TimePickerDialog.OnTimeSetListener {
|
||||||
|
override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) {
|
||||||
|
reminderHour = hourOfDay
|
||||||
|
reminderMin = minute
|
||||||
|
populateReminder()
|
||||||
|
}
|
||||||
|
override fun onTimeCleared(view: RadialPickerLayout?) {
|
||||||
|
reminderHour = -1
|
||||||
|
reminderMin = -1
|
||||||
|
reminderDays = WeekdayList.EVERY_DAY
|
||||||
|
populateReminder()
|
||||||
|
}
|
||||||
|
}, currentHour, currentMin, is24HourMode, androidColor)
|
||||||
|
dialog.show(supportFragmentManager, "timePicker")
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.reminderDatePicker.setOnClickListener {
|
||||||
|
val dialog = WeekdayPickerDialog()
|
||||||
|
dialog.setListener { days ->
|
||||||
|
reminderDays = days
|
||||||
|
if (reminderDays.isEmpty) reminderDays = WeekdayList.EVERY_DAY
|
||||||
|
populateReminder()
|
||||||
|
}
|
||||||
|
dialog.setSelectedDays(reminderDays)
|
||||||
|
dialog.show(supportFragmentManager, "dayPicker")
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.buttonSave.setOnClickListener {
|
||||||
|
if(validate()) save()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (fragment in supportFragmentManager.fragments) {
|
||||||
|
(fragment as DialogFragment).dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun save() {
|
||||||
|
val component = (application as HabitsApplication).component
|
||||||
|
val habit = component.modelFactory.buildHabit()
|
||||||
|
|
||||||
|
var original: Habit? = null
|
||||||
|
if (habitId >= 0) {
|
||||||
|
original = component.habitList.getById(habitId)!!
|
||||||
|
habit.copyFrom(original)
|
||||||
|
}
|
||||||
|
|
||||||
|
habit.name = nameInput.text.trim().toString()
|
||||||
|
habit.question = questionInput.text.trim().toString()
|
||||||
|
habit.description = notesInput.text.trim().toString()
|
||||||
|
habit.color = paletteColor
|
||||||
|
if (reminderHour >= 0) {
|
||||||
|
habit.setReminder(Reminder(reminderHour, reminderMin, reminderDays))
|
||||||
|
}
|
||||||
|
habit.frequency = Frequency(freqNum, freqDen)
|
||||||
|
habit.unit = ""
|
||||||
|
habit.targetValue = 1.0
|
||||||
|
habit.type = Habit.YES_NO_HABIT
|
||||||
|
|
||||||
|
val command = if (habitId >= 0) {
|
||||||
|
component.editHabitCommandFactory.create(component.habitList, original, habit)
|
||||||
|
} else {
|
||||||
|
component.createHabitCommandFactory.create(component.habitList, habit)
|
||||||
|
}
|
||||||
|
component.commandRunner.execute(command, null)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validate(): Boolean {
|
||||||
|
if (nameInput.text.isEmpty()) {
|
||||||
|
nameInput.error = getString(R.string.validation_name_should_not_be_blank)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateReminder() {
|
||||||
|
if (reminderHour < 0) {
|
||||||
|
binding.reminderTimePicker.text = getString(R.string.reminder_off)
|
||||||
|
binding.reminderDatePicker.visibility = View.GONE
|
||||||
|
binding.reminderDivider.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
val time = AndroidDateUtils.formatTime(this, reminderHour, reminderMin)
|
||||||
|
val daysArray = reminderDays.toArray()
|
||||||
|
binding.reminderTimePicker.text = time
|
||||||
|
binding.reminderDatePicker.visibility = View.VISIBLE
|
||||||
|
binding.reminderDivider.visibility = View.VISIBLE
|
||||||
|
binding.reminderDatePicker.text = AndroidDateUtils.formatWeekdayList(this, daysArray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateFrequency() {
|
||||||
|
val label = when {
|
||||||
|
freqNum == 1 && freqDen == 1 -> getString(R.string.every_day)
|
||||||
|
freqNum == 1 && freqDen == 7 -> getString(R.string.every_week)
|
||||||
|
freqNum == 1 && freqDen > 1 -> getString(R.string.every_x_days, freqDen)
|
||||||
|
freqDen == 7 -> getString(R.string.x_times_per_week, freqNum)
|
||||||
|
freqDen == 31 -> getString(R.string.x_times_per_month, freqNum)
|
||||||
|
else -> "Unknown"
|
||||||
|
}
|
||||||
|
binding.frequencyPicker.text = label
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateColors() {
|
||||||
|
androidColor = PaletteUtils.getColor(this, paletteColor)
|
||||||
|
binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor)
|
||||||
|
if (!themeSwitcher.isNightMode) {
|
||||||
|
val darkerAndroidColor = ColorUtils.mixColors(Color.BLACK, androidColor, 0.15f)
|
||||||
|
window.statusBarColor = darkerAndroidColor
|
||||||
|
binding.toolbar.setBackgroundColor(androidColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(state: Bundle) {
|
||||||
|
super.onSaveInstanceState(state)
|
||||||
|
with(state) {
|
||||||
|
putLong("habitId", habitId)
|
||||||
|
putInt("paletteColor", paletteColor)
|
||||||
|
putInt("androidColor", androidColor)
|
||||||
|
putInt("freqNum", freqNum)
|
||||||
|
putInt("freqDen", freqDen)
|
||||||
|
putInt("reminderHour", reminderHour)
|
||||||
|
putInt("reminderMin", reminderMin)
|
||||||
|
putInt("reminderDays", reminderDays.toInteger())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit;
|
|
||||||
|
|
||||||
import android.app.*;
|
|
||||||
import android.content.*;
|
|
||||||
import android.os.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.*;
|
|
||||||
import android.text.format.*;
|
|
||||||
import android.view.*;
|
|
||||||
|
|
||||||
import com.android.datetimepicker.time.TimePickerDialog;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.activities.*;
|
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*;
|
|
||||||
import org.isoron.uhabits.activities.habits.edit.views.*;
|
|
||||||
import org.isoron.uhabits.core.commands.*;
|
|
||||||
import org.isoron.uhabits.core.models.*;
|
|
||||||
import org.isoron.uhabits.core.preferences.*;
|
|
||||||
|
|
||||||
import butterknife.*;
|
|
||||||
|
|
||||||
import static android.view.View.*;
|
|
||||||
|
|
||||||
public class EditHabitDialog extends AppCompatDialogFragment
|
|
||||||
{
|
|
||||||
public static final String BUNDLE_HABIT_ID = "habitId";
|
|
||||||
|
|
||||||
public static final String BUNDLE_HABIT_TYPE = "habitType";
|
|
||||||
|
|
||||||
private static final String WEEKDAY_PICKER_TAG = "weekdayPicker";
|
|
||||||
|
|
||||||
protected Habit originalHabit;
|
|
||||||
|
|
||||||
protected Preferences prefs;
|
|
||||||
|
|
||||||
protected CommandRunner commandRunner;
|
|
||||||
|
|
||||||
protected HabitList habitList;
|
|
||||||
|
|
||||||
protected HabitsApplicationComponent component;
|
|
||||||
|
|
||||||
protected ModelFactory modelFactory;
|
|
||||||
|
|
||||||
@BindView(R.id.namePanel)
|
|
||||||
NameDescriptionPanel namePanel;
|
|
||||||
|
|
||||||
@BindView(R.id.reminderPanel)
|
|
||||||
ReminderPanel reminderPanel;
|
|
||||||
|
|
||||||
@BindView(R.id.frequencyPanel)
|
|
||||||
FrequencyPanel frequencyPanel;
|
|
||||||
|
|
||||||
@BindView(R.id.targetPanel)
|
|
||||||
TargetPanel targetPanel;
|
|
||||||
|
|
||||||
private ColorPickerDialogFactory colorPickerDialogFactory;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getTheme()
|
|
||||||
{
|
|
||||||
HabitsActivity activity = (HabitsActivity) getActivity();
|
|
||||||
return activity.getComponent().getThemeSwitcher().getDialogTheme();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityCreated(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onActivityCreated(savedInstanceState);
|
|
||||||
|
|
||||||
HabitsActivity activity = (HabitsActivity) getActivity();
|
|
||||||
colorPickerDialogFactory =
|
|
||||||
activity.getComponent().getColorPickerDialogFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater,
|
|
||||||
ViewGroup container,
|
|
||||||
Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
View view;
|
|
||||||
view = inflater.inflate(R.layout.edit_habit, container, false);
|
|
||||||
|
|
||||||
initDependencies();
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
|
|
||||||
originalHabit = parseHabitFromArguments();
|
|
||||||
getDialog().setTitle(getTitle());
|
|
||||||
|
|
||||||
populateForm();
|
|
||||||
setupReminderController();
|
|
||||||
setupNameController();
|
|
||||||
|
|
||||||
restoreChildFragmentListeners();
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
||||||
final Dialog dialog = super.onCreateDialog(savedInstanceState);
|
|
||||||
final Window window = dialog.getWindow();
|
|
||||||
if (window != null) {
|
|
||||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
|
||||||
}
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getTitle()
|
|
||||||
{
|
|
||||||
if (originalHabit != null) return R.string.edit_habit;
|
|
||||||
else return R.string.create_habit;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void saveHabit(@NonNull Habit habit)
|
|
||||||
{
|
|
||||||
if (originalHabit == null)
|
|
||||||
{
|
|
||||||
commandRunner.execute(component
|
|
||||||
.getCreateHabitCommandFactory()
|
|
||||||
.create(habitList, habit), null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
commandRunner.execute(component.getEditHabitCommandFactory().
|
|
||||||
create(habitList, originalHabit, habit), originalHabit.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTypeFromArguments()
|
|
||||||
{
|
|
||||||
return getArguments().getInt(BUNDLE_HABIT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initDependencies()
|
|
||||||
{
|
|
||||||
Context appContext = getContext().getApplicationContext();
|
|
||||||
HabitsApplication app = (HabitsApplication) appContext;
|
|
||||||
|
|
||||||
component = app.getComponent();
|
|
||||||
prefs = component.getPreferences();
|
|
||||||
habitList = component.getHabitList();
|
|
||||||
commandRunner = component.getCommandRunner();
|
|
||||||
modelFactory = component.getModelFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.buttonDiscard)
|
|
||||||
void onButtonDiscardClick()
|
|
||||||
{
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.buttonSave)
|
|
||||||
void onSaveButtonClick()
|
|
||||||
{
|
|
||||||
int type = getTypeFromArguments();
|
|
||||||
|
|
||||||
if (!namePanel.validate()) return;
|
|
||||||
if (type == Habit.YES_NO_HABIT && !frequencyPanel.validate()) return;
|
|
||||||
if (type == Habit.NUMBER_HABIT && !targetPanel.validate()) return;
|
|
||||||
|
|
||||||
Habit habit = modelFactory.buildHabit();
|
|
||||||
if( originalHabit != null )
|
|
||||||
habit.copyFrom(originalHabit);
|
|
||||||
habit.setName(namePanel.getName());
|
|
||||||
habit.setDescription(namePanel.getDescription());
|
|
||||||
habit.setQuestion(namePanel.getQuestion());
|
|
||||||
habit.setColor(namePanel.getColor());
|
|
||||||
habit.setReminder(reminderPanel.getReminder());
|
|
||||||
habit.setFrequency(frequencyPanel.getFrequency());
|
|
||||||
habit.setUnit(targetPanel.getUnit());
|
|
||||||
habit.setTargetValue(targetPanel.getTargetValue());
|
|
||||||
habit.setType(type);
|
|
||||||
|
|
||||||
saveHabit(habit);
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Habit parseHabitFromArguments()
|
|
||||||
{
|
|
||||||
Bundle arguments = getArguments();
|
|
||||||
if (arguments == null) return null;
|
|
||||||
|
|
||||||
Long id = (Long) arguments.get(BUNDLE_HABIT_ID);
|
|
||||||
if (id == null) return null;
|
|
||||||
|
|
||||||
Habit habit = habitList.getById(id);
|
|
||||||
if (habit == null) throw new IllegalStateException();
|
|
||||||
|
|
||||||
return habit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateForm()
|
|
||||||
{
|
|
||||||
Habit habit = modelFactory.buildHabit();
|
|
||||||
habit.setFrequency(Frequency.DAILY);
|
|
||||||
habit.setColor(prefs.getDefaultHabitColor(habit.getColor()));
|
|
||||||
habit.setType(getTypeFromArguments());
|
|
||||||
|
|
||||||
if (originalHabit != null) habit.copyFrom(originalHabit);
|
|
||||||
|
|
||||||
if (habit.isNumerical()) frequencyPanel.setVisibility(GONE);
|
|
||||||
else targetPanel.setVisibility(GONE);
|
|
||||||
|
|
||||||
namePanel.populateFrom(habit);
|
|
||||||
frequencyPanel.setFrequency(habit.getFrequency());
|
|
||||||
targetPanel.setTargetValue(habit.getTargetValue());
|
|
||||||
targetPanel.setUnit(habit.getUnit());
|
|
||||||
if (habit.hasReminder()) reminderPanel.setReminder(habit.getReminder());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupNameController()
|
|
||||||
{
|
|
||||||
namePanel.setController(new NameDescriptionPanel.Controller()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onColorPickerClicked(int previousColor)
|
|
||||||
{
|
|
||||||
ColorPickerDialog picker =
|
|
||||||
colorPickerDialogFactory.create(previousColor);
|
|
||||||
|
|
||||||
picker.setListener(c ->
|
|
||||||
{
|
|
||||||
prefs.setDefaultHabitColor(c);
|
|
||||||
namePanel.setColor(c);
|
|
||||||
});
|
|
||||||
|
|
||||||
picker.show(getFragmentManager(), "picker");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupReminderController()
|
|
||||||
{
|
|
||||||
reminderPanel.setController(new ReminderPanel.Controller()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onTimeClicked(int currentHour, int currentMin)
|
|
||||||
{
|
|
||||||
TimePickerDialog timePicker;
|
|
||||||
boolean is24HourMode = DateFormat.is24HourFormat(getContext());
|
|
||||||
timePicker =
|
|
||||||
TimePickerDialog.newInstance(reminderPanel, currentHour,
|
|
||||||
currentMin, is24HourMode);
|
|
||||||
timePicker.show(getFragmentManager(), "timePicker");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWeekdayClicked(WeekdayList currentDays)
|
|
||||||
{
|
|
||||||
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
|
||||||
dialog.setListener(reminderPanel);
|
|
||||||
dialog.setSelectedDays(currentDays);
|
|
||||||
dialog.show(getChildFragmentManager(), WEEKDAY_PICKER_TAG);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restoreChildFragmentListeners()
|
|
||||||
{
|
|
||||||
final WeekdayPickerDialog dialog =
|
|
||||||
(WeekdayPickerDialog) getChildFragmentManager()
|
|
||||||
.findFragmentByTag(WEEKDAY_PICKER_TAG);
|
|
||||||
if(dialog != null) dialog.setListener(reminderPanel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit;
|
|
||||||
|
|
||||||
import android.os.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.core.models.*;
|
|
||||||
|
|
||||||
import javax.inject.*;
|
|
||||||
|
|
||||||
import static org.isoron.uhabits.activities.habits.edit.EditHabitDialog.*;
|
|
||||||
|
|
||||||
public class EditHabitDialogFactory
|
|
||||||
{
|
|
||||||
@Inject
|
|
||||||
public EditHabitDialogFactory()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public EditHabitDialog createBoolean()
|
|
||||||
{
|
|
||||||
EditHabitDialog dialog = new EditHabitDialog();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putInt(BUNDLE_HABIT_TYPE, Habit.YES_NO_HABIT);
|
|
||||||
dialog.setArguments(args);
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EditHabitDialog createNumerical()
|
|
||||||
{
|
|
||||||
EditHabitDialog dialog = new EditHabitDialog();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putInt(BUNDLE_HABIT_TYPE, Habit.NUMBER_HABIT);
|
|
||||||
dialog.setArguments(args);
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EditHabitDialog edit(@NonNull Habit habit)
|
|
||||||
{
|
|
||||||
if (habit.getId() == null)
|
|
||||||
throw new IllegalArgumentException("habit not saved");
|
|
||||||
|
|
||||||
EditHabitDialog dialog = new EditHabitDialog();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putLong(BUNDLE_HABIT_ID, habit.getId());
|
|
||||||
args.putInt(BUNDLE_HABIT_TYPE, habit.getType());
|
|
||||||
dialog.setArguments(args);
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.activities.habits.edit
|
||||||
|
|
||||||
|
import android.os.*
|
||||||
|
import android.view.*
|
||||||
|
import androidx.appcompat.app.*
|
||||||
|
import org.isoron.uhabits.*
|
||||||
|
import org.isoron.uhabits.databinding.*
|
||||||
|
import org.isoron.uhabits.intents.*
|
||||||
|
|
||||||
|
class HabitTypeDialog : AppCompatDialogFragment() {
|
||||||
|
override fun getTheme() = R.style.Translucent
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
val binding = SelectHabitTypeBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
binding.buttonYesNo.setOnClickListener {
|
||||||
|
val intent = IntentFactory().startEditActivity(activity!!)
|
||||||
|
startActivity(intent)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.buttonMeasurable.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.buttonSubjective.setOnClickListener{
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.background.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit.views;
|
|
||||||
|
|
||||||
import android.content.*;
|
|
||||||
import android.text.*;
|
|
||||||
import android.util.*;
|
|
||||||
import android.view.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.AppCompatEditText;
|
|
||||||
|
|
||||||
import org.isoron.androidbase.utils.*;
|
|
||||||
import org.isoron.uhabits.*;
|
|
||||||
|
|
||||||
import static org.isoron.uhabits.utils.AttributeSetUtils.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An EditText that shows an example usage when there is no text
|
|
||||||
* currently set. The example disappears when the widget gains focus.
|
|
||||||
*/
|
|
||||||
public class ExampleEditText extends AppCompatEditText
|
|
||||||
implements View.OnFocusChangeListener
|
|
||||||
{
|
|
||||||
|
|
||||||
private String example;
|
|
||||||
|
|
||||||
private String realText;
|
|
||||||
|
|
||||||
private int color;
|
|
||||||
|
|
||||||
private int exampleColor;
|
|
||||||
|
|
||||||
private int inputType;
|
|
||||||
|
|
||||||
public ExampleEditText(Context context, @Nullable AttributeSet attrs)
|
|
||||||
{
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
if (attrs != null)
|
|
||||||
example = getAttribute(context, attrs, "example", "");
|
|
||||||
|
|
||||||
inputType = getInputType();
|
|
||||||
realText = getText().toString();
|
|
||||||
color = getCurrentTextColor();
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRealText()
|
|
||||||
{
|
|
||||||
if(hasFocus()) return getText().toString();
|
|
||||||
else return realText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View v, boolean hasFocus)
|
|
||||||
{
|
|
||||||
if (!hasFocus) realText = getText().toString();
|
|
||||||
updateText();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExample(String example)
|
|
||||||
{
|
|
||||||
this.example = example;
|
|
||||||
updateText();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRealText(@NonNull String realText)
|
|
||||||
{
|
|
||||||
this.realText = realText;
|
|
||||||
updateText();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init()
|
|
||||||
{
|
|
||||||
StyledResources sr = new StyledResources(getContext());
|
|
||||||
exampleColor = sr.getColor(R.attr.mediumContrastTextColor);
|
|
||||||
setOnFocusChangeListener(this);
|
|
||||||
updateText();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateText()
|
|
||||||
{
|
|
||||||
if (realText.isEmpty() && !isFocused())
|
|
||||||
{
|
|
||||||
setTextColor(exampleColor);
|
|
||||||
setText(example);
|
|
||||||
setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setText(realText);
|
|
||||||
setTextColor(color);
|
|
||||||
setInputType(inputType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit.views;
|
|
||||||
|
|
||||||
import android.annotation.*;
|
|
||||||
import android.content.*;
|
|
||||||
import android.content.res.*;
|
|
||||||
import android.util.*;
|
|
||||||
import android.view.*;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.core.models.*;
|
|
||||||
|
|
||||||
import butterknife.*;
|
|
||||||
|
|
||||||
import static org.isoron.uhabits.R.id.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class FrequencyPanel extends FrameLayout
|
|
||||||
{
|
|
||||||
@BindView(numerator)
|
|
||||||
TextView tvNumerator;
|
|
||||||
|
|
||||||
@BindView(R.id.denominator)
|
|
||||||
TextView tvDenominator;
|
|
||||||
|
|
||||||
@BindView(R.id.spinner)
|
|
||||||
Spinner spinner;
|
|
||||||
|
|
||||||
@BindView(R.id.customFreqPanel)
|
|
||||||
ViewGroup customFreqPanel;
|
|
||||||
|
|
||||||
public FrequencyPanel(@NonNull Context context,
|
|
||||||
@Nullable AttributeSet attrs)
|
|
||||||
{
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
View view = inflate(context, R.layout.edit_habit_frequency, null);
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
addView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Frequency getFrequency()
|
|
||||||
{
|
|
||||||
String freqNum = tvNumerator.getText().toString();
|
|
||||||
String freqDen = tvDenominator.getText().toString();
|
|
||||||
|
|
||||||
if (!freqNum.isEmpty() && !freqDen.isEmpty())
|
|
||||||
{
|
|
||||||
int numerator = Integer.parseInt(freqNum);
|
|
||||||
int denominator = Integer.parseInt(freqDen);
|
|
||||||
return new Frequency(numerator, denominator);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Frequency.DAILY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
public void setFrequency(@NonNull Frequency freq)
|
|
||||||
{
|
|
||||||
int position = getQuickSelectPosition(freq);
|
|
||||||
|
|
||||||
if (position >= 0) showSimplifiedFrequency(position);
|
|
||||||
else showCustomFrequency();
|
|
||||||
|
|
||||||
tvNumerator.setText(Integer.toString(freq.getNumerator()));
|
|
||||||
tvDenominator.setText(Integer.toString(freq.getDenominator()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnItemSelected(R.id.spinner)
|
|
||||||
public void onFrequencySelected(int position)
|
|
||||||
{
|
|
||||||
if (position < 0 || position > 4) throw new IllegalArgumentException();
|
|
||||||
int freqNums[] = { 1, 1, 2, 5, 3 };
|
|
||||||
int freqDens[] = { 1, 7, 7, 7, 7 };
|
|
||||||
setFrequency(new Frequency(freqNums[position], freqDens[position]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validate()
|
|
||||||
{
|
|
||||||
boolean valid = true;
|
|
||||||
Resources res = getResources();
|
|
||||||
|
|
||||||
String freqNum = tvNumerator.getText().toString();
|
|
||||||
String freqDen = tvDenominator.getText().toString();
|
|
||||||
|
|
||||||
if (freqDen.isEmpty())
|
|
||||||
{
|
|
||||||
tvDenominator.setError(
|
|
||||||
res.getString(R.string.validation_show_not_be_blank));
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (freqNum.isEmpty())
|
|
||||||
{
|
|
||||||
tvNumerator.setError(
|
|
||||||
res.getString(R.string.validation_show_not_be_blank));
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) return false;
|
|
||||||
|
|
||||||
int numerator = Integer.parseInt(freqNum);
|
|
||||||
int denominator = Integer.parseInt(freqDen);
|
|
||||||
|
|
||||||
if (numerator <= 0)
|
|
||||||
{
|
|
||||||
tvNumerator.setError(
|
|
||||||
res.getString(R.string.validation_number_should_be_positive));
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numerator > denominator)
|
|
||||||
{
|
|
||||||
tvNumerator.setError(
|
|
||||||
res.getString(R.string.validation_at_most_one_rep_per_day));
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getQuickSelectPosition(@NonNull Frequency freq)
|
|
||||||
{
|
|
||||||
if (freq.equals(Frequency.DAILY)) return 0;
|
|
||||||
if (freq.equals(Frequency.WEEKLY)) return 1;
|
|
||||||
if (freq.equals(Frequency.TWO_TIMES_PER_WEEK)) return 2;
|
|
||||||
if (freq.equals(Frequency.FIVE_TIMES_PER_WEEK)) return 3;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showCustomFrequency()
|
|
||||||
{
|
|
||||||
spinner.setVisibility(View.GONE);
|
|
||||||
customFreqPanel.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showSimplifiedFrequency(int quickSelectPosition)
|
|
||||||
{
|
|
||||||
spinner.setVisibility(View.VISIBLE);
|
|
||||||
spinner.setSelection(quickSelectPosition);
|
|
||||||
customFreqPanel.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit.views;
|
|
||||||
|
|
||||||
import android.content.*;
|
|
||||||
import android.content.res.*;
|
|
||||||
import android.os.*;
|
|
||||||
import android.util.*;
|
|
||||||
import android.view.*;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.activities.common.views.*;
|
|
||||||
import org.isoron.uhabits.core.models.*;
|
|
||||||
import org.isoron.uhabits.utils.*;
|
|
||||||
|
|
||||||
import butterknife.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class NameDescriptionPanel extends FrameLayout
|
|
||||||
{
|
|
||||||
@BindView(R.id.tvName)
|
|
||||||
EditText tvName;
|
|
||||||
|
|
||||||
@BindView(R.id.tvQuestion)
|
|
||||||
ExampleEditText tvQuestion;
|
|
||||||
|
|
||||||
@BindView(R.id.tvDescription)
|
|
||||||
ExampleEditText tvDescription;
|
|
||||||
|
|
||||||
private int color;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private Controller controller;
|
|
||||||
|
|
||||||
public NameDescriptionPanel(@NonNull Context context,
|
|
||||||
@Nullable AttributeSet attrs)
|
|
||||||
{
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
View view = inflate(context, R.layout.edit_habit_name, null);
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
addView(view);
|
|
||||||
|
|
||||||
controller = new Controller() {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getColor()
|
|
||||||
{
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int color)
|
|
||||||
{
|
|
||||||
this.color = color;
|
|
||||||
tvName.setTextColor(PaletteUtils.getColor(getContext(), color));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String getDescription()
|
|
||||||
{
|
|
||||||
return tvDescription.getRealText().trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String getQuestion()
|
|
||||||
{
|
|
||||||
return tvQuestion.getRealText().trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return tvName.getText().toString().trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void populateFrom(@NonNull Habit habit)
|
|
||||||
{
|
|
||||||
Resources res = getResources();
|
|
||||||
|
|
||||||
if(habit.isNumerical())
|
|
||||||
tvQuestion.setExample(res.getString(R.string.example_question_numerical));
|
|
||||||
else
|
|
||||||
tvQuestion.setExample(res.getString(R.string.example_question_boolean));
|
|
||||||
|
|
||||||
setColor(habit.getColor());
|
|
||||||
tvName.setText(habit.getName());
|
|
||||||
tvQuestion.setRealText(habit.getQuestion());
|
|
||||||
tvDescription.setRealText(habit.getDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validate()
|
|
||||||
{
|
|
||||||
Resources res = getResources();
|
|
||||||
|
|
||||||
if (getName().isEmpty())
|
|
||||||
{
|
|
||||||
tvName.setError(
|
|
||||||
res.getString(R.string.validation_name_should_not_be_blank));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onRestoreInstanceState(Parcelable state)
|
|
||||||
{
|
|
||||||
BundleSavedState bss = (BundleSavedState) state;
|
|
||||||
setColor(bss.bundle.getInt("color"));
|
|
||||||
super.onRestoreInstanceState(bss.getSuperState());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Parcelable onSaveInstanceState()
|
|
||||||
{
|
|
||||||
Parcelable superState = super.onSaveInstanceState();
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putInt("color", color);
|
|
||||||
return new BundleSavedState(superState, bundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.buttonPickColor)
|
|
||||||
void showColorPicker()
|
|
||||||
{
|
|
||||||
controller.onColorPickerClicked(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setController(@NonNull Controller controller)
|
|
||||||
{
|
|
||||||
this.controller = controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Controller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called when the user has clicked the widget to select a new
|
|
||||||
* color for the habit.
|
|
||||||
*
|
|
||||||
* @param previousColor the color previously selected
|
|
||||||
*/
|
|
||||||
default void onColorPickerClicked(int previousColor) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit.views;
|
|
||||||
|
|
||||||
import android.content.*;
|
|
||||||
import android.os.*;
|
|
||||||
import android.util.*;
|
|
||||||
import android.view.*;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.android.datetimepicker.time.*;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*;
|
|
||||||
import org.isoron.uhabits.activities.common.views.*;
|
|
||||||
import org.isoron.uhabits.core.models.*;
|
|
||||||
import org.isoron.uhabits.utils.*;
|
|
||||||
|
|
||||||
import butterknife.*;
|
|
||||||
|
|
||||||
public class ReminderPanel extends FrameLayout
|
|
||||||
implements TimePickerDialog.OnTimeSetListener,
|
|
||||||
WeekdayPickerDialog.OnWeekdaysPickedListener
|
|
||||||
{
|
|
||||||
@BindView(R.id.tvReminderTime)
|
|
||||||
TextView tvReminderTime;
|
|
||||||
|
|
||||||
@BindView(R.id.llReminderDays)
|
|
||||||
ViewGroup llReminderDays;
|
|
||||||
|
|
||||||
@BindView(R.id.tvReminderDays)
|
|
||||||
TextView tvReminderDays;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Reminder reminder;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private Controller controller;
|
|
||||||
|
|
||||||
public ReminderPanel(@NonNull Context context, @Nullable AttributeSet attrs)
|
|
||||||
{
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
View view = inflate(context, R.layout.edit_habit_reminder, null);
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
addView(view);
|
|
||||||
|
|
||||||
controller = new Controller() {};
|
|
||||||
setReminder(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Reminder getReminder()
|
|
||||||
{
|
|
||||||
return reminder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReminder(@Nullable Reminder reminder)
|
|
||||||
{
|
|
||||||
this.reminder = reminder;
|
|
||||||
|
|
||||||
if (reminder == null)
|
|
||||||
{
|
|
||||||
tvReminderTime.setText(R.string.reminder_off);
|
|
||||||
llReminderDays.setVisibility(View.GONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Context ctx = getContext();
|
|
||||||
String time = AndroidDateUtils.formatTime(ctx, reminder.getHour(), reminder.getMinute());
|
|
||||||
tvReminderTime.setText(time);
|
|
||||||
llReminderDays.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
boolean weekdays[] = reminder.getDays().toArray();
|
|
||||||
tvReminderDays.setText(AndroidDateUtils.formatWeekdayList(ctx, weekdays));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTimeCleared(RadialPickerLayout view)
|
|
||||||
{
|
|
||||||
setReminder(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTimeSet(RadialPickerLayout view, int hour, int minute)
|
|
||||||
{
|
|
||||||
WeekdayList days = WeekdayList.EVERY_DAY;
|
|
||||||
if (reminder != null) days = reminder.getDays();
|
|
||||||
setReminder(new Reminder(hour, minute, days));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWeekdaysSet(WeekdayList selectedDays)
|
|
||||||
{
|
|
||||||
if (reminder == null) return;
|
|
||||||
if (selectedDays.isEmpty()) selectedDays = WeekdayList.EVERY_DAY;
|
|
||||||
|
|
||||||
setReminder(new Reminder(reminder.getHour(), reminder.getMinute(),
|
|
||||||
selectedDays));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setController(@NonNull Controller controller)
|
|
||||||
{
|
|
||||||
this.controller = controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onRestoreInstanceState(Parcelable state)
|
|
||||||
{
|
|
||||||
BundleSavedState bss = (BundleSavedState) state;
|
|
||||||
if (!bss.bundle.isEmpty())
|
|
||||||
{
|
|
||||||
int days = bss.bundle.getInt("days");
|
|
||||||
int hour = bss.bundle.getInt("hour");
|
|
||||||
int minute = bss.bundle.getInt("minute");
|
|
||||||
reminder = new Reminder(hour, minute, new WeekdayList(days));
|
|
||||||
setReminder(reminder);
|
|
||||||
}
|
|
||||||
super.onRestoreInstanceState(bss.getSuperState());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Parcelable onSaveInstanceState()
|
|
||||||
{
|
|
||||||
Parcelable superState = super.onSaveInstanceState();
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
if (reminder != null)
|
|
||||||
{
|
|
||||||
bundle.putInt("days", reminder.getDays().toInteger());
|
|
||||||
bundle.putInt("hour", reminder.getHour());
|
|
||||||
bundle.putInt("minute", reminder.getMinute());
|
|
||||||
}
|
|
||||||
return new BundleSavedState(superState, bundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.tvReminderTime)
|
|
||||||
void onDateSpinnerClick()
|
|
||||||
{
|
|
||||||
int hour = 8;
|
|
||||||
int min = 0;
|
|
||||||
|
|
||||||
if (reminder != null)
|
|
||||||
{
|
|
||||||
hour = reminder.getHour();
|
|
||||||
min = reminder.getMinute();
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.onTimeClicked(hour, min);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.tvReminderDays)
|
|
||||||
void onWeekdayClicked()
|
|
||||||
{
|
|
||||||
if (reminder == null) return;
|
|
||||||
controller.onWeekdayClicked(reminder.getDays());
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Controller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called when the user has clicked the widget to change the time of
|
|
||||||
* the reminder.
|
|
||||||
*
|
|
||||||
* @param currentHour hour previously picked by the user
|
|
||||||
* @param currentMin minute previously picked by the user
|
|
||||||
*/
|
|
||||||
default void onTimeClicked(int currentHour, int currentMin) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the used has clicked the widget to change the days
|
|
||||||
* of the reminder.
|
|
||||||
*
|
|
||||||
* @param currentDays days previously selected by the user.
|
|
||||||
*/
|
|
||||||
default void onWeekdayClicked(WeekdayList currentDays) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit.views;
|
|
||||||
|
|
||||||
import android.content.*;
|
|
||||||
import android.content.res.*;
|
|
||||||
import android.util.*;
|
|
||||||
import android.view.*;
|
|
||||||
import android.widget.*;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import butterknife.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class TargetPanel extends FrameLayout
|
|
||||||
{
|
|
||||||
private DecimalFormat valueFormatter = new DecimalFormat("#.##");
|
|
||||||
|
|
||||||
@BindView(R.id.tvUnit)
|
|
||||||
ExampleEditText tvUnit;
|
|
||||||
|
|
||||||
@BindView(R.id.tvTargetCount)
|
|
||||||
TextView tvTargetValue;
|
|
||||||
|
|
||||||
public TargetPanel(@NonNull Context context, @Nullable AttributeSet attrs)
|
|
||||||
{
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
View view = inflate(context, R.layout.edit_habit_target, null);
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
addView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getTargetValue()
|
|
||||||
{
|
|
||||||
String sValue = tvTargetValue.getText().toString();
|
|
||||||
return Double.parseDouble(sValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTargetValue(double targetValue)
|
|
||||||
{
|
|
||||||
tvTargetValue.setText(valueFormatter.format(targetValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUnit()
|
|
||||||
{
|
|
||||||
return tvUnit.getRealText();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUnit(String unit)
|
|
||||||
{
|
|
||||||
tvUnit.setRealText(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validate()
|
|
||||||
{
|
|
||||||
Resources res = getResources();
|
|
||||||
String sValue = tvTargetValue.getText().toString();
|
|
||||||
double value = Double.parseDouble(sValue);
|
|
||||||
|
|
||||||
if (value <= 0)
|
|
||||||
{
|
|
||||||
tvTargetValue.setError(
|
|
||||||
res.getString(R.string.validation_number_should_be_positive));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,9 +39,7 @@ class ListHabitsMenu @Inject constructor(
|
|||||||
val nightModeItem = menu.findItem(R.id.actionToggleNightMode)
|
val nightModeItem = menu.findItem(R.id.actionToggleNightMode)
|
||||||
val hideArchivedItem = menu.findItem(R.id.actionHideArchived)
|
val hideArchivedItem = menu.findItem(R.id.actionHideArchived)
|
||||||
val hideCompletedItem = menu.findItem(R.id.actionHideCompleted)
|
val hideCompletedItem = menu.findItem(R.id.actionHideCompleted)
|
||||||
val addNumericalHabit = menu.findItem(R.id.actionCreateNumeralHabit)
|
|
||||||
|
|
||||||
addNumericalHabit.isVisible = preferences.isDeveloper
|
|
||||||
nightModeItem.isChecked = themeSwitcher.isNightMode
|
nightModeItem.isChecked = themeSwitcher.isNightMode
|
||||||
hideArchivedItem.isChecked = !preferences.showArchived
|
hideArchivedItem.isChecked = !preferences.showArchived
|
||||||
hideCompletedItem.isChecked = !preferences.showCompleted
|
hideCompletedItem.isChecked = !preferences.showCompleted
|
||||||
@@ -54,13 +52,8 @@ class ListHabitsMenu @Inject constructor(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.actionCreateBooleanHabit -> {
|
R.id.actionCreateHabit -> {
|
||||||
behavior.onCreateBooleanHabit()
|
behavior.onCreateHabit()
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.actionCreateNumeralHabit -> {
|
|
||||||
behavior.onCreateNumericalHabit()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,14 +58,12 @@ class ListHabitsScreen
|
|||||||
private val commandRunner: CommandRunner,
|
private val commandRunner: CommandRunner,
|
||||||
private val intentFactory: IntentFactory,
|
private val intentFactory: IntentFactory,
|
||||||
private val themeSwitcher: ThemeSwitcher,
|
private val themeSwitcher: ThemeSwitcher,
|
||||||
private val preferences: Preferences,
|
|
||||||
private val adapter: HabitCardListAdapter,
|
private val adapter: HabitCardListAdapter,
|
||||||
private val taskRunner: TaskRunner,
|
private val taskRunner: TaskRunner,
|
||||||
private val exportDBFactory: ExportDBTaskFactory,
|
private val exportDBFactory: ExportDBTaskFactory,
|
||||||
private val importTaskFactory: ImportDataTaskFactory,
|
private val importTaskFactory: ImportDataTaskFactory,
|
||||||
private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory,
|
private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory,
|
||||||
private val colorPickerFactory: ColorPickerDialogFactory,
|
private val colorPickerFactory: ColorPickerDialogFactory,
|
||||||
private val editHabitDialogFactory: EditHabitDialogFactory,
|
|
||||||
private val numberPickerFactory: NumberPickerFactory,
|
private val numberPickerFactory: NumberPickerFactory,
|
||||||
private val behavior: Lazy<ListHabitsBehavior>,
|
private val behavior: Lazy<ListHabitsBehavior>,
|
||||||
private val menu: Lazy<ListHabitsMenu>,
|
private val menu: Lazy<ListHabitsMenu>,
|
||||||
@@ -137,14 +135,9 @@ class ListHabitsScreen
|
|||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showCreateBooleanHabitScreen() {
|
override fun showSelectHabitTypeDialog() {
|
||||||
val dialog = editHabitDialogFactory.createBoolean()
|
val dialog = HabitTypeDialog()
|
||||||
activity.showDialog(dialog, "editHabit")
|
activity.showDialog(dialog, "habitType")
|
||||||
}
|
|
||||||
|
|
||||||
override fun showCreateNumericalHabitScreen() {
|
|
||||||
val dialog = editHabitDialogFactory.createNumerical()
|
|
||||||
activity.showDialog(dialog, "editHabit")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showDeleteConfirmationScreen(callback: OnConfirmedCallback) {
|
override fun showDeleteConfirmationScreen(callback: OnConfirmedCallback) {
|
||||||
@@ -152,8 +145,8 @@ class ListHabitsScreen
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showEditHabitsScreen(habits: List<Habit>) {
|
override fun showEditHabitsScreen(habits: List<Habit>) {
|
||||||
val dialog = editHabitDialogFactory.edit(habits[0])
|
val intent = intentFactory.startEditActivity(activity!!, habits[0])
|
||||||
activity.showDialog(dialog, "editNumericalHabit")
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showFAQScreen() {
|
override fun showFAQScreen() {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.show;
|
package org.isoron.uhabits.activities.habits.show;
|
||||||
|
|
||||||
|
import android.content.*;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.isoron.androidbase.activities.*;
|
import org.isoron.androidbase.activities.*;
|
||||||
@@ -28,6 +30,7 @@ import org.isoron.uhabits.activities.habits.edit.*;
|
|||||||
import org.isoron.uhabits.core.models.*;
|
import org.isoron.uhabits.core.models.*;
|
||||||
import org.isoron.uhabits.core.ui.callbacks.*;
|
import org.isoron.uhabits.core.ui.callbacks.*;
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.*;
|
import org.isoron.uhabits.core.ui.screens.habits.show.*;
|
||||||
|
import org.isoron.uhabits.intents.*;
|
||||||
|
|
||||||
import javax.inject.*;
|
import javax.inject.*;
|
||||||
|
|
||||||
@@ -43,30 +46,30 @@ public class ShowHabitScreen extends BaseScreen
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final Habit habit;
|
private final Habit habit;
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final EditHabitDialogFactory editHabitDialogFactory;
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final ConfirmDeleteDialogFactory confirmDeleteDialogFactory;
|
private final ConfirmDeleteDialogFactory confirmDeleteDialogFactory;
|
||||||
|
|
||||||
private final Lazy<ShowHabitBehavior> behavior;
|
private final Lazy<ShowHabitBehavior> behavior;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final IntentFactory intentFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ShowHabitScreen(@NonNull BaseActivity activity,
|
public ShowHabitScreen(@NonNull BaseActivity activity,
|
||||||
@NonNull Habit habit,
|
@NonNull Habit habit,
|
||||||
@NonNull ShowHabitRootView view,
|
@NonNull ShowHabitRootView view,
|
||||||
@NonNull ShowHabitsMenu menu,
|
@NonNull ShowHabitsMenu menu,
|
||||||
@NonNull EditHabitDialogFactory editHabitDialogFactory,
|
|
||||||
@NonNull ConfirmDeleteDialogFactory confirmDeleteDialogFactory,
|
@NonNull ConfirmDeleteDialogFactory confirmDeleteDialogFactory,
|
||||||
|
@NonNull IntentFactory intentFactory,
|
||||||
@NonNull Lazy<ShowHabitBehavior> behavior)
|
@NonNull Lazy<ShowHabitBehavior> behavior)
|
||||||
{
|
{
|
||||||
super(activity);
|
super(activity);
|
||||||
|
this.intentFactory = intentFactory;
|
||||||
setMenu(menu);
|
setMenu(menu);
|
||||||
setRootView(view);
|
setRootView(view);
|
||||||
|
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
this.behavior = behavior;
|
this.behavior = behavior;
|
||||||
this.editHabitDialogFactory = editHabitDialogFactory;
|
|
||||||
this.confirmDeleteDialogFactory = confirmDeleteDialogFactory;
|
this.confirmDeleteDialogFactory = confirmDeleteDialogFactory;
|
||||||
view.setController(this);
|
view.setController(this);
|
||||||
}
|
}
|
||||||
@@ -102,7 +105,8 @@ public class ShowHabitScreen extends BaseScreen
|
|||||||
@Override
|
@Override
|
||||||
public void showEditHabitScreen(@NonNull Habit habit)
|
public void showEditHabitScreen(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
activity.showDialog(editHabitDialogFactory.edit(habit), "editHabit");
|
Intent intent = intentFactory.startEditActivity(activity, habit);
|
||||||
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ package org.isoron.uhabits.intents
|
|||||||
|
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.net.*
|
import android.net.*
|
||||||
|
import org.isoron.androidbase.activities.*
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.*
|
||||||
import org.isoron.uhabits.activities.about.*
|
import org.isoron.uhabits.activities.about.*
|
||||||
|
import org.isoron.uhabits.activities.habits.edit.*
|
||||||
import org.isoron.uhabits.activities.habits.show.*
|
import org.isoron.uhabits.activities.habits.show.*
|
||||||
import org.isoron.uhabits.activities.intro.*
|
import org.isoron.uhabits.activities.intro.*
|
||||||
import org.isoron.uhabits.activities.settings.*
|
import org.isoron.uhabits.activities.settings.*
|
||||||
@@ -81,4 +83,14 @@ class IntentFactory
|
|||||||
|
|
||||||
fun codeContributors(context: Context) =
|
fun codeContributors(context: Context) =
|
||||||
buildViewIntent(context.getString(R.string.codeContributorsURL))
|
buildViewIntent(context.getString(R.string.codeContributorsURL))
|
||||||
|
|
||||||
|
fun startEditActivity(context: Context): Intent {
|
||||||
|
return Intent(context, EditHabitActivity::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startEditActivity(context: Context, habit: Habit): Intent {
|
||||||
|
val intent = startEditActivity(context)
|
||||||
|
intent.putExtra("habitId", habit.id)
|
||||||
|
return intent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.isoron.uhabits.notifications;
|
|||||||
|
|
||||||
|
|
||||||
import android.app.*;
|
import android.app.*;
|
||||||
|
import android.graphics.*;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -66,7 +67,8 @@ public class SnoozeDelayPickerActivity extends FragmentActivity
|
|||||||
},
|
},
|
||||||
calendar.get(Calendar.HOUR_OF_DAY),
|
calendar.get(Calendar.HOUR_OF_DAY),
|
||||||
calendar.get(Calendar.MINUTE),
|
calendar.get(Calendar.MINUTE),
|
||||||
DateFormat.is24HourFormat(this));
|
DateFormat.is24HourFormat(this),
|
||||||
|
Color.BLUE);
|
||||||
dialog.show(getSupportFragmentManager(), "timePicker");
|
dialog.show(getSupportFragmentManager(), "timePicker");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="?attr/highContrastReverseTextColor"/>
|
||||||
|
<stroke android:width="1dp" android:color="?attr/lowContrastTextColor" />
|
||||||
|
<corners android:radius="4dp"/>
|
||||||
|
<padding
|
||||||
|
android:left="8dp"
|
||||||
|
android:top="8dp"
|
||||||
|
android:right="8dp"
|
||||||
|
android:bottom="8dp" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="?attr/highContrastReverseTextColor"/>
|
||||||
|
<stroke android:width="1dp" android:color="?attr/lowContrastTextColor" />
|
||||||
|
<corners android:radius="4dp"/>
|
||||||
|
<padding
|
||||||
|
android:left="0dp"
|
||||||
|
android:top="8dp"
|
||||||
|
android:right="0dp"
|
||||||
|
android:bottom="0dp" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="?attr/mediumContrastTextColor"
|
||||||
|
android:pathData="M7,10l5,5 5,-5z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
~
|
||||||
|
~ This file is part of Loop Habit Tracker.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by the
|
||||||
|
~ Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
~ option) any later version.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
~ more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License along
|
||||||
|
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ripple
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="?colorAccent">
|
||||||
|
<item android:gravity="center">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="?cardBgColor"/>
|
||||||
|
<corners android:radius="5dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/highContrastReverseTextColor"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".activities.habits.edit.EditHabitActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:minHeight="?attr/actionBarSize"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||||
|
app:title="@string/create_habit"
|
||||||
|
app:titleTextColor="@color/white">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/buttonSave"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:text="@string/save"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
app:rippleColor="@color/white"
|
||||||
|
app:strokeColor="@color/white" />
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="8dp">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Title and color -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<!-- Habit Title -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/name" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/nameInput"
|
||||||
|
style="@style/FormInput"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:inputType="textCapSentences"
|
||||||
|
android:hint="@string/exercise_habit_name"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Habit Color -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:paddingStart="0dp">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="Color" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/colorButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:backgroundTint="#E23673" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Habit Question -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:paddingTop="4dp">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/question" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/questionInput"
|
||||||
|
style="@style/FormInput"
|
||||||
|
android:inputType="textCapSentences|textMultiLine"
|
||||||
|
android:hint="@string/example_question_boolean"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Frequency -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:paddingTop="4dp">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/frequency" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/FormDropdown"
|
||||||
|
android:id="@+id/frequencyPicker"
|
||||||
|
android:textColor="?attr/highContrastTextColor"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Reminder -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/reminder" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/FormDropdown"
|
||||||
|
android:id="@+id/reminderTimePicker"
|
||||||
|
android:text="@string/reminder_off" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
style="@style/FormDivider"
|
||||||
|
android:id="@+id/reminderDivider"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/FormDropdown"
|
||||||
|
android:id="@+id/reminderDatePicker"
|
||||||
|
android:text="" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Notes -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/notes" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/notesInput"
|
||||||
|
style="@style/FormInput"
|
||||||
|
android:inputType="textCapSentences|textMultiLine"
|
||||||
|
android:hint="@string/example_notes" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
~
|
|
||||||
~ This file is part of Loop Habit Tracker.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by the
|
|
||||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
~ option) any later version.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
~ more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License along
|
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/container"
|
|
||||||
style="@style/dialogForm"
|
|
||||||
tools:context=".activities.habits.edit.EditHabitDialog"
|
|
||||||
tools:ignore="MergeRootFrame">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/formPanel"
|
|
||||||
style="@style/dialogFormPanel">
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.NameDescriptionPanel
|
|
||||||
android:id="@+id/namePanel"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.FrequencyPanel
|
|
||||||
android:id="@+id/frequencyPanel"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.TargetPanel
|
|
||||||
android:id="@+id/targetPanel"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.ReminderPanel
|
|
||||||
android:id="@+id/reminderPanel"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
style="?android:attr/buttonBarStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="end"
|
|
||||||
android:paddingStart="0dp"
|
|
||||||
android:paddingLeft="0dp"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:paddingRight="16dp">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/buttonDiscard"
|
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/discard" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/buttonSave"
|
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/save" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
~
|
|
||||||
~ This file is part of Loop Habit Tracker.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by the
|
|
||||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
~ option) any later version.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
~ more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License along
|
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout style="@style/dialogFormRow"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormLabel"
|
|
||||||
android:text="@string/repeat"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatSpinner
|
|
||||||
android:id="@+id/spinner"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="25dp"
|
|
||||||
android:entries="@array/frequencyQuickSelect"
|
|
||||||
android:minWidth="400dp"
|
|
||||||
android:theme="@style/dialogFormText"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<org.apmem.tools.layouts.FlowLayout
|
|
||||||
android:id="@+id/customFreqPanel"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="fill"
|
|
||||||
android:visibility="visible">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/numerator"
|
|
||||||
style="@style/dialogFormInputLargeNumber"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormText"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/times_every"/>
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/denominator"
|
|
||||||
style="@style/dialogFormInputLargeNumber"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormText"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingLeft="12dp"
|
|
||||||
android:text="@string/days"/>
|
|
||||||
|
|
||||||
</org.apmem.tools.layouts.FlowLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
~
|
|
||||||
~ This file is part of Loop Habit Tracker.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by the
|
|
||||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
~ option) any later version.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
~ more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License along
|
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://isoron.org/android"
|
|
||||||
xmlns:app1="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minWidth="300dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/tilName"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app1:layout_constraintEnd_toStartOf="@+id/buttonPickColor"
|
|
||||||
app1:layout_constraintHorizontal_weight="6"
|
|
||||||
app1:layout_constraintStart_toStartOf="parent"
|
|
||||||
app1:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/tvName"
|
|
||||||
style="@style/dialogFormInput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="start"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:hint="@string/name">
|
|
||||||
|
|
||||||
<requestFocus />
|
|
||||||
</EditText>
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/buttonPickColor"
|
|
||||||
style="@style/dialogFormInputColor"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:contentDescription="@string/color_picker_default_title"
|
|
||||||
android:src="?dialogIconChangeColor"
|
|
||||||
app1:layout_constraintBottom_toBottomOf="@id/tilName"
|
|
||||||
app1:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app1:layout_constraintHorizontal_weight="1"
|
|
||||||
app1:layout_constraintStart_toEndOf="@+id/tilName"
|
|
||||||
app1:layout_constraintTop_toTopOf="@id/tilName" />
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/tilQuestion"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/question"
|
|
||||||
app1:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app1:layout_constraintStart_toStartOf="parent"
|
|
||||||
app1:layout_constraintTop_toBottomOf="@id/tilName">
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
|
||||||
android:id="@+id/tvQuestion"
|
|
||||||
style="@style/dialogFormInput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:example="@string/example_question_numerical" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:hint="@string/notes"
|
|
||||||
app1:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app1:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app1:layout_constraintStart_toStartOf="parent"
|
|
||||||
app1:layout_constraintTop_toBottomOf="@id/tilQuestion">
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
|
||||||
android:id="@+id/tvDescription"
|
|
||||||
style="@style/dialogFormInputMultiline"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="top"
|
|
||||||
app:example="@string/example_notes" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
~
|
|
||||||
~ This file is part of Loop Habit Tracker.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by the
|
|
||||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
~ option) any later version.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
~ more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License along
|
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
style="@style/dialogFormRow"
|
|
||||||
android:layout_marginTop="12dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormLabel"
|
|
||||||
android:text="@string/reminder"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvReminderTime"
|
|
||||||
style="@style/dialogFormSpinner"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/llReminderDays"
|
|
||||||
style="@style/dialogFormRow"
|
|
||||||
android:layout_marginTop="12dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormLabel"
|
|
||||||
android:text=""/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvReminderDays"
|
|
||||||
style="@style/dialogFormSpinner"/>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
~
|
|
||||||
~ This file is part of Loop Habit Tracker.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by the
|
|
||||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
~ option) any later version.
|
|
||||||
~
|
|
||||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
~ more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License along
|
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout style="@style/dialogFormRow"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://isoron.org/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormLabel"
|
|
||||||
android:text="@string/target"/>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="2">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/tvTargetCount"
|
|
||||||
style="@style/dialogFormInput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/count"
|
|
||||||
android:inputType="numberDecimal"
|
|
||||||
android:text="@string/default_count"
|
|
||||||
/>
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="2">
|
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
|
||||||
android:id="@+id/tvUnit"
|
|
||||||
style="@style/dialogFormInput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/unit"
|
|
||||||
android:inputType="text"
|
|
||||||
app:example="@string/example_units"/>
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/everyDayRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/every_day" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/everyXDaysRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Every" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/everyXDaysTextView"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/bg_input_box"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxLength="2"
|
||||||
|
android:text="3" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="days" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/xTimesPerWeekRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/xTimesPerWeekTextView"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/bg_input_box"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxLength="2"
|
||||||
|
android:text="5" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="times per week" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/xTimesPerMonthRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/xTimesPerMonthTextView"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/bg_input_box"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxLength="2"
|
||||||
|
android:text="10" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="times per month" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
~
|
||||||
|
~ This file is part of Loop Habit Tracker.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by the
|
||||||
|
~ Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
~ option) any later version.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
~ more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License along
|
||||||
|
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="#a0000000"
|
||||||
|
android:clickable="true"
|
||||||
|
android:id="@+id/background"
|
||||||
|
>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/buttonYesNo"
|
||||||
|
style="@style/SelectHabitTypeButton">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/SelectHabitTypeButtonTitle"
|
||||||
|
android:text="@string/yes_or_no" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/SelectHabitTypeButtonBody"
|
||||||
|
android:text="@string/yes_or_no_example" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/buttonMeasurable"
|
||||||
|
style="@style/SelectHabitTypeButton">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/SelectHabitTypeButtonTitle"
|
||||||
|
android:text="@string/measurable" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/SelectHabitTypeButtonBody"
|
||||||
|
android:text="@string/measurable_example" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/buttonSubjective"
|
||||||
|
style="@style/SelectHabitTypeButton">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/SelectHabitTypeButtonTitle"
|
||||||
|
android:text="@string/subjective" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/SelectHabitTypeButtonBody"
|
||||||
|
android:text="@string/subjective_example" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/actionCreateBooleanHabit"
|
android:id="@+id/actionCreateHabit"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:icon="?iconAdd"
|
android:icon="?iconAdd"
|
||||||
android:title="@string/add_habit"
|
android:title="@string/add_habit"
|
||||||
@@ -96,11 +96,4 @@
|
|||||||
android:title="@string/about"
|
android:title="@string/about"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/actionCreateNumeralHabit"
|
|
||||||
android:enabled="true"
|
|
||||||
android:title="Add Numerical Habit"
|
|
||||||
android:orderInCategory="200"
|
|
||||||
app:showAsAction="never" />
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|||||||
@@ -245,6 +245,15 @@
|
|||||||
<string name="first_day_of_the_week">First day of the week</string>
|
<string name="first_day_of_the_week">First day of the week</string>
|
||||||
<string name="default_reminder_question">Have you completed this habit today?</string>
|
<string name="default_reminder_question">Have you completed this habit today?</string>
|
||||||
<string name="notes">Notes</string>
|
<string name="notes">Notes</string>
|
||||||
<string name="example_notes">You can put whatever you want here!</string>
|
<string name="example_notes">(Optional)</string>
|
||||||
|
|
||||||
|
<string name="yes_or_no_example">e.g. Did you wake up early today? Did you exercise? Did you play chess?</string>
|
||||||
|
<string name="measurable">Measurable</string>
|
||||||
|
<string name="measurable_example">e.g. How many miles did you run today? How many pages did you read? How many calories did you eat?</string>
|
||||||
|
<string name="subjective">Subjective</string>
|
||||||
|
<string name="subjective_example">e.g. Are you felling happy today? Definitely, somewhat, not at all? How frequently did you snack? Very often, sometimes, never?</string>
|
||||||
|
<string name="x_times_per_week">%d times per week</string>
|
||||||
|
<string name="x_times_per_month">%d times per month</string>
|
||||||
|
<string name="exercise_habit_name">e.g. Exercise</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
|
<style name="AppBaseTheme" parent="@style/Theme.MaterialComponents.Light.NoActionBar">
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
<item name="android:dialogTheme">@style/Theme.AppCompat.Light.Dialog</item>
|
<item name="android:dialogTheme">@style/Theme.AppCompat.Light.Dialog</item>
|
||||||
<item name="android:alertDialogTheme">@style/Theme.AppCompat.Light.Dialog</item>
|
<item name="android:alertDialogTheme">@style/Theme.AppCompat.Light.Dialog</item>
|
||||||
|
<item name="android:navigationBarColor">?attr/colorPrimary</item>
|
||||||
|
|
||||||
<item name="windowActionModeOverlay">true</item>
|
<item name="windowActionModeOverlay">true</item>
|
||||||
<item name="actionModeBackground">@color/blue_grey_700</item>
|
<item name="actionModeBackground">@color/blue_grey_700</item>
|
||||||
@@ -30,9 +31,9 @@
|
|||||||
<item name="selectedBackground">@drawable/selected_box_light</item>
|
<item name="selectedBackground">@drawable/selected_box_light</item>
|
||||||
<item name="cardBackground">@drawable/card_light_background</item>
|
<item name="cardBackground">@drawable/card_light_background</item>
|
||||||
|
|
||||||
<item name="colorPrimary">@color/blue_grey_800</item>
|
<item name="colorPrimary">#363636</item>
|
||||||
<item name="colorPrimaryDark">@color/blue_grey_900</item>
|
<item name="colorPrimaryDark">#303030</item>
|
||||||
<item name="colorAccent">?aboutScreenColor</item>
|
<item name="colorAccent">#303030</item>
|
||||||
<item name="cardBgColor">@color/grey_50</item>
|
<item name="cardBgColor">@color/grey_50</item>
|
||||||
<item name="windowBackgroundColor">@color/grey_200</item>
|
<item name="windowBackgroundColor">@color/grey_200</item>
|
||||||
<item name="headerBackgroundColor">@color/grey_200</item>
|
<item name="headerBackgroundColor">@color/grey_200</item>
|
||||||
@@ -74,7 +75,7 @@
|
|||||||
<item name="android:textSize">@dimen/smallTextSize</item>
|
<item name="android:textSize">@dimen/smallTextSize</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppBaseThemeDark" parent="@style/Theme.AppCompat.NoActionBar">
|
<style name="AppBaseThemeDark" parent="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
<item name="android:dialogTheme">@style/Theme.AppCompat.Dialog</item>
|
<item name="android:dialogTheme">@style/Theme.AppCompat.Dialog</item>
|
||||||
<item name="android:alertDialogTheme">@style/Theme.AppCompat.Dialog</item>
|
<item name="android:alertDialogTheme">@style/Theme.AppCompat.Dialog</item>
|
||||||
@@ -256,4 +257,86 @@
|
|||||||
<style name="ScrollableRecyclerViewStyle" parent="android:Widget">
|
<style name="ScrollableRecyclerViewStyle" parent="android:Widget">
|
||||||
<item name="android:scrollbars">vertical</item>
|
<item name="android:scrollbars">vertical</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="SelectHabitTypeButton">
|
||||||
|
<item name="android:orientation">vertical</item>
|
||||||
|
<item name="android:paddingTop">14dp</item>
|
||||||
|
<item name="android:paddingBottom">16dp</item>
|
||||||
|
<item name="android:paddingLeft">16dp</item>
|
||||||
|
<item name="android:paddingRight">16dp</item>
|
||||||
|
<item name="android:layout_marginLeft">16dp</item>
|
||||||
|
<item name="android:layout_marginRight">16dp</item>
|
||||||
|
<item name="android:layout_marginBottom">8dp</item>
|
||||||
|
<item name="android:layout_marginTop">8dp</item>
|
||||||
|
<item name="android:elevation">6dp</item>
|
||||||
|
<item name="android:background">@drawable/round_ripple</item>
|
||||||
|
<item name="android:clickable">true</item>
|
||||||
|
<item name="android:selectable">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="SelectHabitTypeButtonTitle">
|
||||||
|
<item name="android:textSize">20sp</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
|
<item name="android:layout_marginBottom">8dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="SelectHabitTypeButtonBody">
|
||||||
|
<item name="android:textSize">@dimen/smallTextSize</item>
|
||||||
|
<item name="android:lineSpacingMultiplier">1.25</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Translucent">
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
|
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
<item name="android:windowTranslucentStatus">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FormLabel">
|
||||||
|
<item name="android:layout_width">wrap_content</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_marginStart">8dp</item>
|
||||||
|
<item name="android:layout_marginTop">-17dp</item>
|
||||||
|
<item name="android:layout_marginBottom">-4dp</item>
|
||||||
|
<item name="android:background">?attr/highContrastReverseTextColor</item>
|
||||||
|
<item name="android:paddingStart">8dp</item>
|
||||||
|
<item name="android:paddingEnd">8dp</item>
|
||||||
|
<item name="android:textSize">@dimen/smallerTextSize</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FormInput">
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:background">@color/transparent</item>
|
||||||
|
<item name="android:paddingLeft">16dp</item>
|
||||||
|
<item name="android:paddingRight">16dp</item>
|
||||||
|
<item name="android:paddingTop">16dp</item>
|
||||||
|
<item name="android:paddingBottom">16dp</item>
|
||||||
|
<item name="android:textSize">@dimen/regularTextSize</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FormDropdown">
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:drawableEnd">@drawable/ic_arrow_drop_down_dark</item>
|
||||||
|
<item name="android:padding">16dp</item>
|
||||||
|
<item name="android:text">@string/every_day</item>
|
||||||
|
<item name="android:textSize">@dimen/regularTextSize</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FormInnerBox">
|
||||||
|
<item name="android:background">@drawable/bg_input_group</item>
|
||||||
|
<item name="android:clipChildren">false</item>
|
||||||
|
<item name="android:clipToPadding">false</item>
|
||||||
|
<item name="android:orientation">vertical</item>
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">match_parent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FormDivider">
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">1dp</item>
|
||||||
|
<item name="android:background">?attr/lowContrastTextColor</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -61,14 +61,9 @@ public class ListHabitsMenuBehavior
|
|||||||
updateAdapterFilter();
|
updateAdapterFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCreateBooleanHabit()
|
public void onCreateHabit()
|
||||||
{
|
{
|
||||||
screen.showCreateBooleanHabitScreen();
|
screen.showSelectHabitTypeDialog();
|
||||||
}
|
|
||||||
|
|
||||||
public void onCreateNumericalHabit()
|
|
||||||
{
|
|
||||||
screen.showCreateNumericalHabitScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onViewFAQ()
|
public void onViewFAQ()
|
||||||
@@ -150,12 +145,10 @@ public class ListHabitsMenuBehavior
|
|||||||
|
|
||||||
void showAboutScreen();
|
void showAboutScreen();
|
||||||
|
|
||||||
void showCreateBooleanHabitScreen();
|
|
||||||
|
|
||||||
void showCreateNumericalHabitScreen();
|
|
||||||
|
|
||||||
void showFAQScreen();
|
void showFAQScreen();
|
||||||
|
|
||||||
void showSettingsScreen();
|
void showSettingsScreen();
|
||||||
|
|
||||||
|
void showSelectHabitTypeDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ public class ListHabitsSelectionMenuBehavior
|
|||||||
public void onEditHabits()
|
public void onEditHabits()
|
||||||
{
|
{
|
||||||
screen.showEditHabitsScreen(adapter.getSelected());
|
screen.showEditHabitsScreen(adapter.getSelected());
|
||||||
|
adapter.clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUnarchiveHabits()
|
public void onUnarchiveHabits()
|
||||||
|
|||||||
Reference in New Issue
Block a user