Created DaysOfWeek class
This commit is contained in:
parent
a8e2a88140
commit
ba41c1311e
@ -4,9 +4,8 @@ apply plugin: 'com.neenbedankt.android-apt'
|
|||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 23
|
||||||
buildToolsVersion "23.0.3"
|
buildToolsVersion "23.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.philliphsu.clock"
|
applicationId 'com.philliphsu.clock2'
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 1
|
versionCode 1
|
||||||
@ -18,18 +17,20 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
productFlavors {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
// Required -- JUnit 4 framework
|
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
// Optional -- Mockito framework
|
|
||||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||||
|
testCompile 'org.robolectric:robolectric:3.0'
|
||||||
provided 'com.google.auto.value:auto-value:1.2'
|
provided 'com.google.auto.value:auto-value:1.2'
|
||||||
apt 'com.google.auto.value:auto-value:1.2'
|
apt 'com.google.auto.value:auto-value:1.2'
|
||||||
compile 'com.android.support:appcompat-v7:23.2.1'
|
compile 'com.android.support:appcompat-v7:23.2.1'
|
||||||
compile 'com.android.support:design:23.2.1'
|
compile 'com.android.support:design:23.2.1'
|
||||||
compile 'com.android.support:support-v4:23.2.1'
|
compile 'com.android.support:support-v4:23.2.1'
|
||||||
compile 'com.android.support:recyclerview-v7:23.2.1'
|
compile 'com.android.support:recyclerview-v7:23.2.1'
|
||||||
|
compile 'com.jakewharton:butterknife:7.0.1'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@ -2,30 +2,38 @@ package com.philliphsu.clock2;
|
|||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import static com.philliphsu.clock2.DaysOfWeek.SATURDAY;
|
||||||
|
import static com.philliphsu.clock2.DaysOfWeek.SUNDAY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Phillip Hsu on 5/26/2016.
|
* Created by Phillip Hsu on 5/26/2016.
|
||||||
*/
|
*/
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class Alarm {
|
public abstract class Alarm {
|
||||||
private static final int MAX_MINUTES_CAN_SNOOZE = 30;
|
private static final int MAX_MINUTES_CAN_SNOOZE = 30; // TODO: Delete this along with all snooze stuff.
|
||||||
// Define our own day constants because those in the
|
|
||||||
// Calendar class are not zero-based.
|
|
||||||
public static final int SUNDAY = 0;
|
|
||||||
public static final int MONDAY = 1;
|
|
||||||
public static final int TUESDAY = 2;
|
|
||||||
public static final int WEDNESDAY = 3;
|
|
||||||
public static final int THURSDAY = 4;
|
|
||||||
public static final int FRIDAY = 5;
|
|
||||||
public static final int SATURDAY = 6;
|
|
||||||
public static final int NUM_DAYS = 7;
|
|
||||||
|
|
||||||
// =========== MUTABLE ===========
|
// JSON property names
|
||||||
private long snoozingUntilMillis; // TODO: Not necessary? Can just schedule another alarm w/ AlarmManager.
|
private static final String KEY_ENABLED = "enabled";
|
||||||
|
private static final String KEY_ID = "id";
|
||||||
|
private static final String KEY_HOUR = "hour";
|
||||||
|
private static final String KEY_MINUTES = "minutes";
|
||||||
|
private static final String KEY_RECURRING_DAYS = "recurring_days";
|
||||||
|
private static final String KEY_LABEL = "label";
|
||||||
|
private static final String KEY_RINGTONE = "ringtone";
|
||||||
|
private static final String KEY_VIBRATES = "vibrates";
|
||||||
|
|
||||||
|
// ========= MUTABLE ==============
|
||||||
|
private long snoozingUntilMillis;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
// ===============================
|
// ================================
|
||||||
|
|
||||||
public abstract long id(); // TODO: Counter in the repository. Set this field as the repo creates instances.
|
public abstract long id(); // TODO: Counter in the repository. Set this field as the repo creates instances.
|
||||||
public abstract int hour();
|
public abstract int hour();
|
||||||
public abstract int minutes();
|
public abstract int minutes();
|
||||||
@ -38,6 +46,24 @@ public abstract class Alarm {
|
|||||||
/** Initializes a Builder to the same property values as this instance */
|
/** Initializes a Builder to the same property values as this instance */
|
||||||
public abstract Builder toBuilder();
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Alarm create(JSONObject jsonObject) {
|
||||||
|
try {
|
||||||
|
Alarm alarm = new AutoValue_Alarm.Builder()
|
||||||
|
.id(jsonObject.getLong(KEY_ID))
|
||||||
|
.hour(jsonObject.getInt(KEY_HOUR))
|
||||||
|
.minutes(jsonObject.getInt(KEY_MINUTES))
|
||||||
|
.recurringDays((boolean[]) jsonObject.get(KEY_RECURRING_DAYS))
|
||||||
|
.label(jsonObject.getString(KEY_LABEL))
|
||||||
|
.ringtone(jsonObject.getString(KEY_RINGTONE))
|
||||||
|
.vibrates(jsonObject.getBoolean(KEY_VIBRATES))
|
||||||
|
.build();
|
||||||
|
alarm.setEnabled(jsonObject.getBoolean(KEY_ENABLED));
|
||||||
|
return alarm;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
// Unfortunately, default values must be provided for generated Builders.
|
// Unfortunately, default values must be provided for generated Builders.
|
||||||
// Fields that were not set when build() is called will throw an exception.
|
// Fields that were not set when build() is called will throw an exception.
|
||||||
@ -46,12 +72,15 @@ public abstract class Alarm {
|
|||||||
.id(-1)
|
.id(-1)
|
||||||
.hour(0)
|
.hour(0)
|
||||||
.minutes(0)
|
.minutes(0)
|
||||||
.recurringDays(new boolean[NUM_DAYS])
|
.recurringDays(new boolean[DaysOfWeek.NUM_DAYS])
|
||||||
.label("")
|
.label("")
|
||||||
.ringtone("")
|
.ringtone("")
|
||||||
.vibrates(false);
|
.vibrates(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
// TODO: Snoozing functionality not necessary. Delete methods.
|
||||||
|
|
||||||
public void snooze(int minutes) {
|
public void snooze(int minutes) {
|
||||||
if (minutes <= 0 || minutes > MAX_MINUTES_CAN_SNOOZE)
|
if (minutes <= 0 || minutes > MAX_MINUTES_CAN_SNOOZE)
|
||||||
throw new IllegalArgumentException("Cannot snooze for "+minutes+" minutes");
|
throw new IllegalArgumentException("Cannot snooze for "+minutes+" minutes");
|
||||||
@ -59,7 +88,7 @@ public abstract class Alarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long snoozingUntil() {
|
public long snoozingUntil() {
|
||||||
return snoozingUntilMillis;
|
return isSnoozed() ? snoozingUntilMillis : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSnoozed() {
|
public boolean isSnoozed() {
|
||||||
@ -70,6 +99,8 @@ public abstract class Alarm {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
@ -89,9 +120,14 @@ public abstract class Alarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasRecurrence() {
|
public boolean hasRecurrence() {
|
||||||
|
return numRecurringDays() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int numRecurringDays() {
|
||||||
|
int count = 0;
|
||||||
for (boolean b : recurringDays())
|
for (boolean b : recurringDays())
|
||||||
if (b) return true;
|
if (b) count++;
|
||||||
return false;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ringsAt() {
|
public long ringsAt() {
|
||||||
@ -133,6 +169,22 @@ public abstract class Alarm {
|
|||||||
return ringsIn() <= hours * 3600000;
|
return ringsIn() <= hours * 3600000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONObject toJsonObject() {
|
||||||
|
try {
|
||||||
|
return new JSONObject()
|
||||||
|
.put(KEY_ENABLED, enabled)
|
||||||
|
.put(KEY_ID, id())
|
||||||
|
.put(KEY_HOUR, hour())
|
||||||
|
.put(KEY_MINUTES, minutes())
|
||||||
|
.put(KEY_RECURRING_DAYS, new JSONArray(recurringDays()))
|
||||||
|
.put(KEY_LABEL, label())
|
||||||
|
.put(KEY_RINGTONE, ringtone())
|
||||||
|
.put(KEY_VIBRATES, vibrates());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@AutoValue.Builder
|
@AutoValue.Builder
|
||||||
public abstract static class Builder {
|
public abstract static class Builder {
|
||||||
// Builder is mutable, so these are inherently setter methods.
|
// Builder is mutable, so these are inherently setter methods.
|
||||||
@ -166,14 +218,15 @@ public abstract class Alarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkDay(int day) {
|
||||||
|
if (day < SUNDAY || day > SATURDAY) {
|
||||||
|
throw new IllegalArgumentException("Invalid day of week: " + day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void checkTime(int hour, int minutes) {
|
private static void checkTime(int hour, int minutes) {
|
||||||
if (hour < 0 || hour > 23 || minutes < 0 || minutes > 59) {
|
if (hour < 0 || hour > 23 || minutes < 0 || minutes > 59) {
|
||||||
throw new IllegalStateException("Hour and minutes invalid");
|
throw new IllegalStateException("Hour and minutes invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkDay(int day) {
|
|
||||||
if (day < SUNDAY || day > SATURDAY)
|
|
||||||
throw new IllegalArgumentException("Invalid day " + day);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
93
app/src/main/java/com/philliphsu/clock2/DaysOfWeek.java
Normal file
93
app/src/main/java/com/philliphsu/clock2/DaysOfWeek.java
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package com.philliphsu.clock2;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Phillip Hsu on 5/30/2016.
|
||||||
|
*/
|
||||||
|
public class DaysOfWeek {
|
||||||
|
private static final String TAG = "DaysOfWeek";
|
||||||
|
// DAY_OF_WEEK constants in Calendar class not zero-based
|
||||||
|
public static final int SUNDAY = 0;
|
||||||
|
public static final int MONDAY = 1;
|
||||||
|
public static final int TUESDAY = 2;
|
||||||
|
public static final int WEDNESDAY = 3;
|
||||||
|
public static final int THURSDAY = 4;
|
||||||
|
public static final int FRIDAY = 5;
|
||||||
|
public static final int SATURDAY = 6;
|
||||||
|
public static final int NUM_DAYS = 7;
|
||||||
|
|
||||||
|
private static final int[] DAYS = new int[NUM_DAYS];
|
||||||
|
private static final int[] LABELS_RES = new int[NUM_DAYS];
|
||||||
|
|
||||||
|
static {
|
||||||
|
LABELS_RES[SUNDAY] = R.string.sun;
|
||||||
|
LABELS_RES[MONDAY] = R.string.mon;
|
||||||
|
LABELS_RES[TUESDAY] = R.string.tue;
|
||||||
|
LABELS_RES[WEDNESDAY] = R.string.wed;
|
||||||
|
LABELS_RES[THURSDAY] = R.string.thu;
|
||||||
|
LABELS_RES[FRIDAY] = R.string.fri;
|
||||||
|
LABELS_RES[SATURDAY] = R.string.sat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Context sAppContext;
|
||||||
|
private static DaysOfWeek sInstance;
|
||||||
|
private static String sLastPreferredFirstDay;
|
||||||
|
|
||||||
|
public static DaysOfWeek getInstance(Context context) {
|
||||||
|
sAppContext = context.getApplicationContext();
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
// TODO First day of week preference. Entries are the full days' names and values are their respective integers.
|
||||||
|
String preferredFirstDay = prefs.getString("", "1");
|
||||||
|
if (sInstance == null || !preferredFirstDay.equals(sLastPreferredFirstDay)) {
|
||||||
|
sLastPreferredFirstDay = preferredFirstDay;
|
||||||
|
sInstance = new DaysOfWeek(Integer.parseInt(preferredFirstDay));
|
||||||
|
}
|
||||||
|
Log.d(TAG, sInstance.toString());
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param weekDay the day constant as defined in this class */
|
||||||
|
public static String getLabel(int weekDay) {
|
||||||
|
return sAppContext.getString(LABELS_RES[weekDay]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the week day whose order is specified by {@code ordinalDay} */
|
||||||
|
// Compiler complains if annotated with @Day
|
||||||
|
public int weekDay(int ordinalDay) {
|
||||||
|
if (ordinalDay < 0 || ordinalDay > 6)
|
||||||
|
throw new ArrayIndexOutOfBoundsException("Ordinal day out of range");
|
||||||
|
return DAYS[ordinalDay];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DaysOfWeek{"
|
||||||
|
+ "DAYS=" + Arrays.toString(DAYS)
|
||||||
|
+ "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private DaysOfWeek(int firstDayOfWeek /*Compiler complains if annotated with @Day*/) {
|
||||||
|
if (firstDayOfWeek != SATURDAY && firstDayOfWeek != SUNDAY && firstDayOfWeek != MONDAY)
|
||||||
|
throw new IllegalArgumentException("Invalid first day of week: " + firstDayOfWeek);
|
||||||
|
DAYS[0] = firstDayOfWeek;
|
||||||
|
for (int i = 1; i < 7; i++) {
|
||||||
|
if (firstDayOfWeek == SATURDAY) {
|
||||||
|
DAYS[i] = i - 1;
|
||||||
|
} else if (firstDayOfWeek == MONDAY) {
|
||||||
|
if (i == 6) {
|
||||||
|
DAYS[i] = SUNDAY;
|
||||||
|
} else {
|
||||||
|
DAYS[i] = i + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DAYS[i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,9 +21,10 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.philliphsu.clock2.alarms.AlarmsFragment;
|
||||||
import com.philliphsu.clock2.ringtone.RingtoneActivity;
|
import com.philliphsu.clock2.ringtone.RingtoneActivity;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity implements AlarmsFragment.OnListFragmentInteractionListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
||||||
@ -153,7 +154,8 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
// getItem is called to instantiate the fragment for the given page.
|
// getItem is called to instantiate the fragment for the given page.
|
||||||
// Return a PlaceholderFragment (defined as a static inner class below).
|
// Return a PlaceholderFragment (defined as a static inner class below).
|
||||||
return PlaceholderFragment.newInstance(position + 1);
|
//return PlaceholderFragment.newInstance(position + 1);
|
||||||
|
return AlarmsFragment.newInstance(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -176,6 +178,11 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListFragmentInteraction(Alarm item) {
|
||||||
|
// TODO react to click
|
||||||
|
}
|
||||||
|
|
||||||
private void scheduleAlarm() {
|
private void scheduleAlarm() {
|
||||||
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
|
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||||
// If there is already an alarm for this Intent scheduled (with the equality of two
|
// If there is already an alarm for this Intent scheduled (with the equality of two
|
||||||
|
|||||||
@ -1,77 +1,186 @@
|
|||||||
package com.philliphsu.clock2.alarms;
|
package com.philliphsu.clock2.alarms;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v7.util.SortedList;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.SwitchCompat;
|
||||||
|
import android.support.v7.widget.util.SortedListAdapterCallback;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
|
import android.text.style.RelativeSizeSpan;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.philliphsu.clock2.Alarm;
|
||||||
|
import com.philliphsu.clock2.DaysOfWeek;
|
||||||
import com.philliphsu.clock2.R;
|
import com.philliphsu.clock2.R;
|
||||||
import com.philliphsu.clock2.alarms.dummy.DummyContent.DummyItem;
|
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
import static com.philliphsu.clock2.DaysOfWeek.NUM_DAYS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link RecyclerView.Adapter} that can display a {@link DummyItem} and makes a call to the
|
* {@link RecyclerView.Adapter} that can display a {@link Alarm} and makes a call to the
|
||||||
* specified {@link AlarmsFragment.OnListFragmentInteractionListener}.
|
* specified {@link AlarmsFragment.OnListFragmentInteractionListener}.
|
||||||
* TODO: Replace the implementation with code for your data type.
|
|
||||||
*/
|
*/
|
||||||
public class AlarmsAdapter extends RecyclerView.Adapter<AlarmsAdapter.ViewHolder> {
|
public class AlarmsAdapter extends RecyclerView.Adapter<AlarmsAdapter.ViewHolder> {
|
||||||
|
private static final RelativeSizeSpan AMPM_SIZE_SPAN = new RelativeSizeSpan(0.5f);
|
||||||
|
|
||||||
private final List<DummyItem> mValues;
|
private final SortedList<Alarm> mItems;
|
||||||
private final AlarmsFragment.OnListFragmentInteractionListener mListener;
|
private final AlarmsFragment.OnListFragmentInteractionListener mListener;
|
||||||
|
|
||||||
public AlarmsAdapter(List<DummyItem> items, AlarmsFragment.OnListFragmentInteractionListener listener) {
|
public AlarmsAdapter(List<Alarm> alarms, AlarmsFragment.OnListFragmentInteractionListener listener) {
|
||||||
mValues = items;
|
mItems = new SortedList<>(Alarm.class, new SortedListAdapterCallback<Alarm>(this) {
|
||||||
|
@Override
|
||||||
|
public int compare(Alarm o1, Alarm o2) {
|
||||||
|
return Long.compare(o1.ringsAt(), o2.ringsAt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(Alarm oldItem, Alarm newItem) {
|
||||||
|
return oldItem.hour() == newItem.hour()
|
||||||
|
&& oldItem.minutes() == newItem.minutes()
|
||||||
|
&& oldItem.isEnabled() == newItem.isEnabled()
|
||||||
|
&& oldItem.label().equals(newItem.label())
|
||||||
|
&& oldItem.ringsIn() == newItem.ringsIn()
|
||||||
|
&& Arrays.equals(oldItem.recurringDays(), newItem.recurringDays())
|
||||||
|
&& oldItem.snoozingUntil() == newItem.snoozingUntil();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(Alarm item1, Alarm item2) {
|
||||||
|
return item1.id() == item2.id();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mItems.addAll(alarms);
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext())
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.fragment_alarms, parent, false);
|
.inflate(R.layout.item_alarm, parent, false);
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view, mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||||
holder.mItem = mValues.get(position);
|
holder.onBind(mItems.get(position));
|
||||||
holder.mIdView.setText(mValues.get(position).id);
|
|
||||||
holder.mContentView.setText(mValues.get(position).content);
|
|
||||||
|
|
||||||
holder.mView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (null != mListener) {
|
|
||||||
// Notify the active callbacks interface (the activity, if the
|
|
||||||
// fragment is attached to one) that an item has been selected.
|
|
||||||
mListener.onListFragmentInteraction(holder.mItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mValues.size();
|
return mItems.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
public final View mView;
|
private final Context mContext;
|
||||||
public final TextView mIdView;
|
private final AlarmsFragment.OnListFragmentInteractionListener mListener;
|
||||||
public final TextView mContentView;
|
private Alarm mItem;
|
||||||
public DummyItem mItem;
|
|
||||||
|
|
||||||
public ViewHolder(View view) {
|
@Bind(R.id.time) TextView mTime;
|
||||||
|
@Bind(R.id.on_off_switch) SwitchCompat mSwitch;
|
||||||
|
@Bind(R.id.label) TextView mLabel;
|
||||||
|
@Bind(R.id.countdown) TextView mCountdown; // TODO: Change type to NextAlarmText, once you move that class to this project
|
||||||
|
@Bind(R.id.recurring_days) TextView mDays;
|
||||||
|
@Bind(R.id.dismiss) Button mDismissButton;
|
||||||
|
|
||||||
|
public ViewHolder(View view, AlarmsFragment.OnListFragmentInteractionListener listener) {
|
||||||
super(view);
|
super(view);
|
||||||
mView = view;
|
ButterKnife.bind(this, view);
|
||||||
mIdView = (TextView) view.findViewById(R.id.id);
|
mContext = view.getContext();
|
||||||
mContentView = (TextView) view.findViewById(R.id.content);
|
mListener = listener;
|
||||||
|
view.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBind(Alarm alarm) {
|
||||||
|
mItem = alarm;
|
||||||
|
String time = DateFormat.getTimeFormat(mContext).format(new Date(alarm.ringsAt()));
|
||||||
|
if (DateFormat.is24HourFormat(mContext)) {
|
||||||
|
mTime.setText(time);
|
||||||
|
} else {
|
||||||
|
// No way around having to construct this on binding
|
||||||
|
SpannableString s = new SpannableString(time);
|
||||||
|
s.setSpan(AMPM_SIZE_SPAN, time.indexOf(" "), time.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
mTime.setText(s, TextView.BufferType.SPANNABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alarm.isEnabled()) {
|
||||||
|
mSwitch.setChecked(true);
|
||||||
|
//TODO:mCountdown.showAsText(alarm.ringsIn());
|
||||||
|
mCountdown.setVisibility(VISIBLE);
|
||||||
|
//todo:mCountdown.getTickHandler().startTicking(true)
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||||
|
// how many hours before alarm is considered upcoming
|
||||||
|
// TODO: shared prefs
|
||||||
|
/*int hoursBeforeUpcoming = Integer.parseInt(prefs.getString(
|
||||||
|
mContext.getString(-1TODO:R.string.key_notify_me_of_upcoming_alarms),
|
||||||
|
"2"));*/
|
||||||
|
if (alarm.ringsWithinHours(2) || alarm.isSnoozed()) {
|
||||||
|
// TODO: Register dynamic broadcast receiver in this class to listen for
|
||||||
|
// when this alarm crosses the upcoming threshold, so we can show this button.
|
||||||
|
mDismissButton.setVisibility(VISIBLE);
|
||||||
|
} else {
|
||||||
|
mDismissButton.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mSwitch.setChecked(false);
|
||||||
|
mCountdown.setVisibility(GONE);
|
||||||
|
//TODO:mCountdown.getTickHandler().stopTicking();
|
||||||
|
mDismissButton.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLabel.setText(alarm.label());
|
||||||
|
if (mLabel.length() == 0 && mCountdown.getVisibility() != VISIBLE) {
|
||||||
|
mLabel.setVisibility(GONE);
|
||||||
|
} else {
|
||||||
|
// needed for proper positioning of mCountdown
|
||||||
|
mLabel.setVisibility(VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numRecurringDays = alarm.numRecurringDays();
|
||||||
|
if (numRecurringDays > 0) {
|
||||||
|
String text;
|
||||||
|
if (numRecurringDays == NUM_DAYS+1) /*TODO: Remove +1*/ {
|
||||||
|
text = mContext.getString(R.string.every_day);
|
||||||
|
} else {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < NUM_DAYS; i++) {
|
||||||
|
// The day at this position in the week
|
||||||
|
int weekDay = DaysOfWeek.getInstance(mContext).weekDay(i);
|
||||||
|
if (alarm.isRecurring(weekDay)) {
|
||||||
|
sb.append(DaysOfWeek.getLabel(weekDay)).append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Cut off the last comma and space
|
||||||
|
sb.delete(sb.length() - 2, sb.length());
|
||||||
|
text = sb.toString();
|
||||||
|
}
|
||||||
|
mDays.setText(text);
|
||||||
|
mDays.setVisibility(VISIBLE);
|
||||||
|
} else {
|
||||||
|
mDays.setVisibility(GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public void onClick(View v) {
|
||||||
return super.toString() + " '" + mContentView.getText() + "'";
|
if (mListener != null) {
|
||||||
|
mListener.onListFragmentInteraction(mItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,9 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.philliphsu.clock2.Alarm;
|
||||||
import com.philliphsu.clock2.R;
|
import com.philliphsu.clock2.R;
|
||||||
import com.philliphsu.clock2.alarms.dummy.DummyContent;
|
import com.philliphsu.clock2.alarms.dummy.DummyContent;
|
||||||
import com.philliphsu.clock2.alarms.dummy.DummyContent.DummyItem;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fragment representing a list of Items.
|
* A fragment representing a list of Items.
|
||||||
@ -32,8 +32,7 @@ public class AlarmsFragment extends Fragment {
|
|||||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||||
* fragment (e.g. upon screen orientation changes).
|
* fragment (e.g. upon screen orientation changes).
|
||||||
*/
|
*/
|
||||||
public AlarmsFragment() {
|
public AlarmsFragment() {}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Customize parameter initialization
|
// TODO: Customize parameter initialization
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -57,7 +56,7 @@ public class AlarmsFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_alarms_list, container, false);
|
View view = inflater.inflate(R.layout.fragment_alarms, container, false);
|
||||||
|
|
||||||
// Set the adapter
|
// Set the adapter
|
||||||
if (view instanceof RecyclerView) {
|
if (view instanceof RecyclerView) {
|
||||||
@ -102,7 +101,6 @@ public class AlarmsFragment extends Fragment {
|
|||||||
* >Communicating with Other Fragments</a> for more information.
|
* >Communicating with Other Fragments</a> for more information.
|
||||||
*/
|
*/
|
||||||
public interface OnListFragmentInteractionListener {
|
public interface OnListFragmentInteractionListener {
|
||||||
// TODO: Update argument type and name
|
void onListFragmentInteraction(Alarm item);
|
||||||
void onListFragmentInteraction(DummyItem item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
package com.philliphsu.clock2.alarms.dummy;
|
package com.philliphsu.clock2.alarms.dummy;
|
||||||
|
|
||||||
|
import com.philliphsu.clock2.Alarm;
|
||||||
|
import com.philliphsu.clock2.DaysOfWeek;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for providing sample content for user interfaces created by
|
* Helper class for providing sample content for user interfaces created by
|
||||||
@ -16,57 +17,31 @@ public class DummyContent {
|
|||||||
/**
|
/**
|
||||||
* An array of sample (dummy) items.
|
* An array of sample (dummy) items.
|
||||||
*/
|
*/
|
||||||
public static final List<DummyItem> ITEMS = new ArrayList<DummyItem>();
|
public static final List<Alarm> ITEMS = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
private static final int COUNT = 10;
|
||||||
* A map of sample (dummy) items, by ID.
|
|
||||||
*/
|
|
||||||
public static final Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
|
|
||||||
|
|
||||||
private static final int COUNT = 25;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Add some sample items.
|
// Add some sample items.
|
||||||
for (int i = 1; i <= COUNT; i++) {
|
for (int i = 1; i <= COUNT; i++) {
|
||||||
addItem(createDummyItem(i));
|
addItem(createAlarm(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addItem(DummyItem item) {
|
private static void addItem(Alarm item) {
|
||||||
ITEMS.add(item);
|
ITEMS.add(item);
|
||||||
ITEM_MAP.put(item.id, item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DummyItem createDummyItem(int position) {
|
private static Alarm createAlarm(int position) {
|
||||||
return new DummyItem(String.valueOf(position), "Item " + position, makeDetails(position));
|
Alarm.Builder b = Alarm.builder();
|
||||||
}
|
if (position % 2 == 0) {
|
||||||
|
b.hour(21).minutes(0);
|
||||||
private static String makeDetails(int position) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("Details about Item: ").append(position);
|
|
||||||
for (int i = 0; i < position; i++) {
|
|
||||||
builder.append("\nMore details information here.");
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A dummy item representing a piece of content.
|
|
||||||
*/
|
|
||||||
public static class DummyItem {
|
|
||||||
public final String id;
|
|
||||||
public final String content;
|
|
||||||
public final String details;
|
|
||||||
|
|
||||||
public DummyItem(String id, String content, String details) {
|
|
||||||
this.id = id;
|
|
||||||
this.content = content;
|
|
||||||
this.details = details;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
boolean[] recurrences = new boolean[DaysOfWeek.NUM_DAYS];
|
||||||
|
recurrences[0] = true;
|
||||||
|
recurrences[5] = true;
|
||||||
|
Alarm a = b.id(position).recurringDays(recurrences).build();
|
||||||
|
a.setEnabled(true);
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
57
app/src/main/res/layout/bar_bottom_navigation.xml
Normal file
57
app/src/main/res/layout/bar_bottom_navigation.xml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<!-- TODO: Use ColorStateLists for both the text and drawable resource to indicate checked state -->
|
||||||
|
|
||||||
|
<ToggleButton
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawableTop="@android:drawable/ic_delete"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:textOff="World Clock"
|
||||||
|
android:textOn="World Clock"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:checked="true"/>
|
||||||
|
|
||||||
|
<ToggleButton
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawableTop="@android:drawable/ic_delete"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:textOff="Alarms"
|
||||||
|
android:textOn="Alarms"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:checked="true"/>
|
||||||
|
|
||||||
|
<ToggleButton
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawableTop="@android:drawable/ic_delete"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:textOff="Timers"
|
||||||
|
android:textOn="Timers"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:checked="true"/>
|
||||||
|
|
||||||
|
<ToggleButton
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawableTop="@android:drawable/ic_delete"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:textOff="Stopwatch"
|
||||||
|
android:textOn="Stopwatch"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:checked="true"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -1,20 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v7.widget.RecyclerView
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/list"
|
||||||
android:layout_height="wrap_content"
|
android:name="com.philliphsu.clock.alarms.AlarmsFragment"
|
||||||
android:orientation="horizontal">
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
<TextView
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/id"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="wrap_content"
|
app:layoutManager="LinearLayoutManager"
|
||||||
android:layout_margin="@dimen/text_margin"
|
tools:context="com.philliphsu.clock2.alarms.AlarmsFragment"
|
||||||
android:textAppearance="?attr/textAppearanceListItem"/>
|
tools:listitem="@layout/item_alarm"/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/content"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/text_margin"
|
|
||||||
android:textAppearance="?attr/textAppearanceListItem"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<android.support.v7.widget.RecyclerView
|
|
||||||
android:id="@+id/list"
|
|
||||||
android:name="com.philliphsu.clock.alarms.AlarmsFragment"
|
|
||||||
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:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
app:layoutManager="LinearLayoutManager"
|
|
||||||
tools:context="com.philliphsu.clock2.alarms.AlarmsFragment"
|
|
||||||
tools:listitem="@layout/fragment_alarms"/>
|
|
||||||
71
app/src/main/res/layout/item_alarm.xml
Normal file
71
app/src/main/res/layout/item_alarm.xml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="@dimen/item_padding_top"
|
||||||
|
android:paddingStart="@dimen/item_padding_start"
|
||||||
|
android:paddingEnd="@dimen/item_padding_end"
|
||||||
|
android:paddingBottom="@dimen/item_padding_bottom"
|
||||||
|
android:background="?selectableItemBackground">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/time_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/item_margin_between_elements">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/time"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="1:20"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||||
|
android:textSize="@dimen/alarm_time_text_size"/>
|
||||||
|
|
||||||
|
<android.support.v7.widget.SwitchCompat
|
||||||
|
android:id="@+id/on_off_switch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?textAppearanceListItem"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="Label"
|
||||||
|
android:layout_below="@id/time_layout"
|
||||||
|
android:layout_marginBottom="@dimen/item_margin_between_elements"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/countdown"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?textAppearanceListItem"
|
||||||
|
android:text="in %dh %dm"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:layout_below="@id/time_layout"
|
||||||
|
android:layout_toEndOf="@id/label"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/recurring_days"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Mon, Tue, Wed, Thu, Fri, Sat, Sun"
|
||||||
|
android:layout_below="@id/label"
|
||||||
|
android:layout_marginBottom="@dimen/item_margin_between_elements"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/dismiss"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/recurring_days"
|
||||||
|
android:text="Dismiss now"
|
||||||
|
style="@style/Widget.AppCompat.Button.Colored"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
10
app/src/main/res/menu/menu_edit_alarm.xml
Normal file
10
app/src/main/res/menu/menu_edit_alarm.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<menu 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"
|
||||||
|
tools:context="com.philliphsu.clock2.editalarm.EditAlarmActivity">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:orderInCategory="100"
|
||||||
|
android:title="@string/action_settings"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
</menu>
|
||||||
@ -3,6 +3,10 @@
|
|||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
<dimen name="appbar_padding_top">8dp</dimen>
|
<dimen name="item_padding_top">8dp</dimen>
|
||||||
<dimen name="text_margin">16dp</dimen>
|
<dimen name="item_padding_bottom">8dp</dimen>
|
||||||
|
<dimen name="item_padding_start">16dp</dimen>
|
||||||
|
<dimen name="item_padding_end">16dp</dimen>
|
||||||
|
<dimen name="item_margin_between_elements">4dp</dimen>
|
||||||
|
<dimen name="alarm_time_text_size">48sp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@ -6,4 +6,14 @@
|
|||||||
<string name="title_activity_ringtone">Clock+</string>
|
<string name="title_activity_ringtone">Clock+</string>
|
||||||
<string name="dummy_button">Dummy Button</string>
|
<string name="dummy_button">Dummy Button</string>
|
||||||
<string name="dummy_content">DUMMY\nCONTENT</string>
|
<string name="dummy_content">DUMMY\nCONTENT</string>
|
||||||
|
<string name="title_activity_edit_alarm">EditAlarmActivity</string>
|
||||||
|
|
||||||
|
<string name="sun">Sun</string>
|
||||||
|
<string name="mon">Mon</string>
|
||||||
|
<string name="tue">Tue</string>
|
||||||
|
<string name="wed">Wed</string>
|
||||||
|
<string name="thu">Thu</string>
|
||||||
|
<string name="fri">Fri</string>
|
||||||
|
<string name="sat">Sat</string>
|
||||||
|
<string name="every_day">Every day</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import org.junit.Test;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import static com.philliphsu.clock2.DaysOfWeek.SUNDAY;
|
||||||
import static java.lang.System.out;
|
import static java.lang.System.out;
|
||||||
import static java.util.Calendar.HOUR_OF_DAY;
|
import static java.util.Calendar.HOUR_OF_DAY;
|
||||||
import static java.util.Calendar.MILLISECOND;
|
import static java.util.Calendar.MILLISECOND;
|
||||||
@ -24,14 +25,14 @@ public class AlarmTest {
|
|||||||
Alarm alarm = Alarm.builder().build();
|
Alarm alarm = Alarm.builder().build();
|
||||||
|
|
||||||
// Some true, some false
|
// Some true, some false
|
||||||
for (int i = Alarm.SUNDAY; i <= Alarm.SATURDAY; i++) {
|
for (int i = SUNDAY; i <= DaysOfWeek.SATURDAY; i++) {
|
||||||
alarm.setRecurring(i, i % 2 == 0);
|
alarm.setRecurring(i, i % 2 == 0);
|
||||||
assertTrue(alarm.isRecurring(i) == (i % 2 == 0));
|
assertTrue(alarm.isRecurring(i) == (i % 2 == 0));
|
||||||
}
|
}
|
||||||
assertTrue(alarm.hasRecurrence());
|
assertTrue(alarm.hasRecurrence());
|
||||||
|
|
||||||
// All false
|
// All false
|
||||||
for (int i = Alarm.SUNDAY; i <= Alarm.SATURDAY; i++) {
|
for (int i = DaysOfWeek.SUNDAY; i <= DaysOfWeek.SATURDAY; i++) {
|
||||||
alarm.setRecurring(i, false);
|
alarm.setRecurring(i, false);
|
||||||
assertFalse(alarm.isRecurring(i));
|
assertFalse(alarm.isRecurring(i));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
package com.philliphsu.clock2;
|
package com.philliphsu.clock2;
|
||||||
|
|
||||||
import com.philliphsu.clock2.ringtone.RingtoneService;
|
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.robolectric.RobolectricGradleTestRunner;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Phillip Hsu on 5/28/2016.
|
* Created by Phillip Hsu on 5/28/2016.
|
||||||
*
|
*
|
||||||
* TODO: Write unit tests...
|
* TODO: Write unit tests...
|
||||||
*/
|
*/
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(RobolectricGradleTestRunner.class)
|
||||||
|
@Config(constants = BuildConfig.class)
|
||||||
public class RingtoneServiceTest {
|
public class RingtoneServiceTest {
|
||||||
|
|
||||||
@Mock RingtoneService mRingtoneService;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user