Commit 7bed0279 authored by Robert Hitt's avatar Robert Hitt
Browse files

Merge branch 'master' into 'material-spec'

# Conflicts:
#   app/src/main/res/layout-land/fragment_notification_dialog.xml
#   app/src/main/res/layout/fragment_notification_dialog.xml
parents 9628597a 3482956e
Pipeline #866 failed with stages
in 16 seconds
......@@ -3,6 +3,8 @@
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".MyApplication"
android:allowBackup="true"
......@@ -37,7 +39,13 @@
<receiver android:name=".util.NotificationReceiver"
android:process=":remote" >
</receiver>
<receiver android:name=".util.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name=".util.NotificationService"
......
......@@ -10,13 +10,14 @@ public class Facility extends RealmObject {
public Facility(String name, String location, MainSchedule mainSchedule,
RealmList<SpecialSchedule> specialSchedules, boolean isOpen,
boolean isFavorited) {
boolean isFavorited, String statusDuration) {
mName = name;
mLocation = location;
mMainSchedule = mainSchedule;
mSpecialSchedules = specialSchedules;
this.isOpen = isOpen;
this.isFavorited = isFavorited;
this.statusDuration = statusDuration;
}
public Facility() {
......@@ -37,6 +38,15 @@ public class Facility extends RealmObject {
private boolean isOpen;
private boolean isFavorited;
private String statusDuration;
public String getStatusDuration() {
return statusDuration;
}
public void setStatusDuration(String statusDuration) {
this.statusDuration = statusDuration;
}
public RealmList<SpecialSchedule> getSpecialSchedules() {
return mSpecialSchedules;
......
package srct.whatsopen.model;
public class NotificationSettings {
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class NotificationSettings extends RealmObject {
public NotificationSettings() {
}
public NotificationSettings(boolean opening, boolean closing, boolean interval_on, boolean interval_15, boolean interval_30, boolean interval_hour) {
public NotificationSettings(String name, boolean opening, boolean closing, boolean interval_on, boolean interval_15, boolean interval_30, boolean interval_hour) {
this.name = name;
this.opening = opening;
this.closing = closing;
this.interval_on = interval_on;
......@@ -15,6 +19,9 @@ public class NotificationSettings {
this.interval_hour = interval_hour;
}
@PrimaryKey
public String name;
public boolean opening;
public boolean closing;
public boolean interval_on;
......
......@@ -12,6 +12,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmList;
......@@ -67,113 +68,68 @@ public class FacilityPresenter {
realm.close();
}
// Finds the next time the facility closes or opens and returns it
public String getStatusDuration(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = getActiveSchedule(facility, now);
if(openTimesList.size() == 0)
return "No open time on schedule";
// Parses the schedule into an HTML string
// Kind of a hacky approach
public String getSchedule(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = getActiveSchedule(facility, now);
int currentDay = (5 + now.get(Calendar.DAY_OF_WEEK)) % 7;
String durationMessage;
if(facility.isOpen()) {
if(facilityDoesNotClose(openTimesList.first())) {
return "Open 24/7";
}
if(openTimesList.size() == 0)
return "No schedule available";
String closingTime = getCurrentEndTime(openTimesList, currentDay);
closingTime = parseTo12HourTime(closingTime);
durationMessage = "Closes at " + closingTime;
if(facilityDoesNotClose(openTimesList))
return "This facility is always open";
return durationMessage;
}
StringBuilder scheduleString = new StringBuilder();
boolean first = true;
for(OpenTimes o : openTimesList) {
if(first)
first = false;
else
scheduleString.append("<br/>");
// Check if the facility opens later today
if(openTimesContains(openTimesList, currentDay)) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
try {
Date currentTime = sdf.parse(sdf.format(now.getTime()));
Date startTime = sdf.parse(getCurrentStartTime(openTimesList, currentDay));
// the current day's schedule should be highlighted
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
scheduleString.append("<strong>");
if(currentTime.compareTo(startTime) < 0) {
String openingTime = getCurrentStartTime(openTimesList, currentDay);
openingTime = parseTo12HourTime(openingTime);
scheduleString.append("<b>" + parseIntToDay(o.getStartDay()) + "</b>: ");
scheduleString.append(parseTo12HourTime(o.getStartTime()));
scheduleString.append(" - ");
scheduleString.append(parseTo12HourTime(o.getEndTime()));
return "Opens today at " + openingTime;
}
} catch (ParseException pe) {
pe.printStackTrace();
return "";
}
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
scheduleString.append("</strong>");
}
// Else return the opening time of the next day
int nextDay = findNextDay(openTimesList, currentDay);
String nextDayStr = parseIntToDay(nextDay);
String openingTime = getCurrentStartTime(openTimesList, nextDay);
openingTime = parseTo12HourTime(openingTime);
durationMessage = "Opens next on " + nextDayStr + " at " + openingTime;
return durationMessage;
return scheduleString.toString();
}
private boolean openTimesContains(RealmList<OpenTimes> openTimesList, int currentDay) {
for(OpenTimes o : openTimesList) {
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
return true;
}
return false;
}
public static boolean facilityDoesNotClose(List<OpenTimes> openTimesList) {
boolean doesNotClose = false;
// Returns the next open day in the list of OpenTimes
private int findNextDay(RealmList<OpenTimes> openTimesList, int current) {
int nextDay = openTimesList.first().getStartDay();
int counter = 0;
for(OpenTimes o : openTimesList) {
if(o.getStartDay() > current) {
nextDay = o.getStartDay();
break;
if(o.getStartTime().equals("00:00:00") && o.getEndTime().equals("23:59:59")
|| o.getEndTime().equals("00:00:00")) {
doesNotClose = true;
}
}
return nextDay;
}
// Returns the end time for the current day
private String getCurrentEndTime(RealmList<OpenTimes> openTimesList, int currentDay) {
String endTime = "";
for(OpenTimes o : openTimesList) {
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
endTime = o.getEndTime();
// check to make sure the facility is open every day of the week
// so, if the start day is 0 and the end day is 6, 6 - 0 + 1 == 7
counter += (o.getEndDay() - o.getStartDay()) + 1;
}
return endTime;
}
// Returns the end time for the current day
private String getCurrentStartTime(RealmList<OpenTimes> openTimesList, int currentDay) {
String startTime = "";
for(OpenTimes o : openTimesList) {
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
startTime = o.getStartTime();
if(counter != 7) {
doesNotClose = false;
}
return startTime;
}
// Currently only works if the Facility has one OpenTimes with
// startDay == 0 and endDay == 6. Should work if the Facility has 7
// OpenTimes
// TODO: fix
private boolean facilityDoesNotClose(OpenTimes openTimes) {
return (openTimes.getStartDay() == 0 && openTimes.getEndDay() == 6 &&
openTimes.getStartTime().equals("00:00:00") &&
openTimes.getEndTime().equals("23:59:59"));
return doesNotClose;
}
// Parses 24 hour formatted time String to 12 hour formatted time String
private String parseTo12HourTime(String time) {
public static String parseTo12HourTime(String time) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
final Date date = sdf.parse(time);
......@@ -185,7 +141,7 @@ public class FacilityPresenter {
}
// Parses an integer to a String of the day of the week
private String parseIntToDay(int day) {
public static String parseIntToDay(int day) {
switch(day) {
case 0:
return "Monday";
......@@ -206,42 +162,6 @@ public class FacilityPresenter {
}
}
// Parses the schedule into an HTML string
// Kind of a hacky approach
public String getSchedule(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = getActiveSchedule(facility, now);
int currentDay = (5 + now.get(Calendar.DAY_OF_WEEK)) % 7;
if(openTimesList.size() == 0)
return "No schedule available";
if(facilityDoesNotClose(openTimesList.first()))
return "This facility is always open";
StringBuilder scheduleString = new StringBuilder();
boolean first = true;
for(OpenTimes o : openTimesList) {
if(first)
first = false;
else
scheduleString.append("<br/>");
// the current day's schedule should be highlighted
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
scheduleString.append("<strong>");
scheduleString.append("<b>" + parseIntToDay(o.getStartDay()) + "</b>: ");
scheduleString.append(parseTo12HourTime(o.getStartTime()));
scheduleString.append(" - ");
scheduleString.append(parseTo12HourTime(o.getEndTime()));
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
scheduleString.append("</strong>");
}
return scheduleString.toString();
}
// Returns the active schedule given the current date
private RealmList<OpenTimes> getActiveSchedule(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = facility.getMainSchedule().getOpenTimesList();
......
......@@ -83,6 +83,7 @@ public class MainPresenter {
// Query SharedReferences for each Facility's favorite status. defaults to false
facility.setFavorited(pref.getBoolean(facility.getName()+"FavoriteStatus", false));
facility.setOpen(getOpenStatus(facility, Calendar.getInstance()));
facility.setStatusDuration(getStatusDuration(facility, Calendar.getInstance()));
}
return facilities;
......@@ -125,20 +126,23 @@ public class MainPresenter {
final String name = facility.getName();
realm.executeTransactionAsync((bgRealm) -> {
RealmResults<Facility> results = realm.where(Facility.class).equalTo("mName", name)
RealmResults<Facility> results = bgRealm.where(Facility.class).equalTo("mName", name)
.findAll();
results.deleteAllFromRealm();
});
realm.close();
}
// Sets the open status of each facility in the Realm instance
// Sets the open status and status duration of each facility in the Realm instance
private void updateOpenStatus() {
Realm realm = Realm.getDefaultInstance();
realm.executeTransactionAsync(bgRealm -> {
List<Facility> facilities = bgRealm.where(Facility.class).findAll();
for(Facility f : facilities) {
f.setOpen(getOpenStatus(f, Calendar.getInstance()));
f.setStatusDuration(getStatusDuration(f, Calendar.getInstance()));
}
}, null, null);
realm.close();
......@@ -161,6 +165,13 @@ public class MainPresenter {
if(currentOpenTimes == null)
return false;
// for some reason in the Api this signifies a facility that's open 24/7, sometimes
// praying for that api v2
if(currentOpenTimes.getStartTime().equals("00:00:00")
&& currentOpenTimes.getEndTime().equals("00:00:00")) {
return true;
}
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
try {
......@@ -179,6 +190,104 @@ public class MainPresenter {
}
}
// Finds the next time the facility closes or opens and returns it
public String getStatusDuration(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = getActiveSchedule(facility, now);
if(openTimesList == null)
return "";
if(openTimesList.size() == 0)
return "No open time on schedule";
int currentDay = (5 + now.get(Calendar.DAY_OF_WEEK)) % 7;
String durationMessage;
if(facility.isOpen()) {
if(FacilityPresenter.facilityDoesNotClose(openTimesList)) {
return "Open 24/7";
}
String closingTime = getCurrentEndTime(openTimesList, currentDay);
closingTime = FacilityPresenter.parseTo12HourTime(closingTime);
durationMessage = "Closes at " + closingTime;
return durationMessage;
}
// Check if the facility opens later today
if(openTimesContains(openTimesList, currentDay)) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
try {
Date currentTime = sdf.parse(sdf.format(now.getTime()));
Date startTime = sdf.parse(getCurrentStartTime(openTimesList, currentDay));
if(currentTime.compareTo(startTime) < 0) {
String openingTime = getCurrentStartTime(openTimesList, currentDay);
openingTime = FacilityPresenter.parseTo12HourTime(openingTime);
return "Opens today at " + openingTime;
}
} catch (ParseException pe) {
pe.printStackTrace();
return "";
}
}
// Else return the opening time of the next day
int nextDay = findNextDay(openTimesList, currentDay);
String nextDayStr = FacilityPresenter.parseIntToDay(nextDay);
String openingTime = getCurrentStartTime(openTimesList, nextDay);
openingTime = FacilityPresenter.parseTo12HourTime(openingTime);
durationMessage = "Opens next on " + nextDayStr + " at " + openingTime;
return durationMessage;
}
private boolean openTimesContains(RealmList<OpenTimes> openTimesList, int currentDay) {
for(OpenTimes o : openTimesList) {
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
return true;
}
return false;
}
// Returns the next open day in the list of OpenTimes
private int findNextDay(RealmList<OpenTimes> openTimesList, int current) {
int nextDay = openTimesList.first().getStartDay();
for(OpenTimes o : openTimesList) {
if(o.getStartDay() > current) {
nextDay = o.getStartDay();
break;
}
}
return nextDay;
}
// Returns the end time for the current day
private String getCurrentEndTime(RealmList<OpenTimes> openTimesList, int currentDay) {
String endTime = "";
for(OpenTimes o : openTimesList) {
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
endTime = o.getEndTime();
}
return endTime;
}
// Returns the end time for the current day
private String getCurrentStartTime(RealmList<OpenTimes> openTimesList, int currentDay) {
String startTime = "";
for(OpenTimes o : openTimesList) {
if(o.getStartDay() <= currentDay && o.getEndDay() >= currentDay)
startTime = o.getStartTime();
}
return startTime;
}
// Returns the active schedule given the current date
private RealmList<OpenTimes> getActiveSchedule(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = facility.getMainSchedule().getOpenTimesList();
......
......@@ -19,6 +19,7 @@ import java.util.Set;
import io.realm.Realm;
import io.realm.RealmList;
import io.realm.RealmResults;
import srct.whatsopen.model.Facility;
import srct.whatsopen.model.NotificationSettings;
import srct.whatsopen.model.OpenTimes;
......@@ -29,12 +30,9 @@ import srct.whatsopen.views.NotificationView;
public class NotificationPresenter {
private NotificationView mNotificationView;
private SharedPreferences pref;
public void attachView(NotificationView view) {
mNotificationView = view;
pref = PreferenceManager
.getDefaultSharedPreferences(mNotificationView.getContext());
}
public void detachView() {
......@@ -44,64 +42,35 @@ public class NotificationPresenter {
// Gets the notification settings from SharedPreferences, parses them to booleans,
// and passes them to the View
public void presentNotifications(String name) {
Set<String> notificationSettingsSet = pref.getStringSet(name+"NotificationSettings", null);
NotificationSettings n = getNotificationSettingsFromSet(notificationSettingsSet);
mNotificationView.setNotificationChecks(n);
}
Realm realm = Realm.getDefaultInstance();
NotificationSettings n = realm.where(NotificationSettings.class).equalTo("name", name)
.findFirst();
realm.close();
public NotificationSettings getNotificationSettingsFromSet(Set<String> set) {
NotificationSettings n = new NotificationSettings();
if(set != null) {
for (String s : set) {
switch (s) {
case "opening": n.opening = true; break;
case "closing": n.closing = true; break;
case "interval_on": n.interval_on = true; break;
case "interval_15": n.interval_15 = true; break;
case "interval_30": n.interval_30 = true; break;
case "interval_hour": n.interval_hour = true; break;
}
}
if(n != null) {
mNotificationView.setNotificationChecks(n);
}
return n;
}
// Returns a String set parsed from the given NotificationSettings
public Set<String> getSetFromNotificationSettings(NotificationSettings n) {
Set<String> set = new HashSet<>(6);
if(n.opening) set.add("opening");
if(n.closing) set.add("closing");
if(n.interval_on) set.add("interval_on");
if(n.interval_15) set.add("interval_15");
if(n.interval_30) set.add("interval_30");
if(n.interval_hour) set.add("interval_hour");
return set;
}
// Saves the notification settings to SharedPreferences and schedules the Notifications
public void saveNotifications(String name, boolean inEditMode, NotificationSettings n) {
public void saveNotifications(boolean inEditMode, NotificationSettings n) {
if(inEditMode) {
editNotifications(name, n);
editNotifications(n);
} else {
setNotifications("Notifications set", name, n);
setNotifications("Notifications set", n);
}
}
// If no checkboxes are set, removes Notifications. Else, sets new Notifications
private void editNotifications(String name, NotificationSettings n) {
private void editNotifications(NotificationSettings n) {
if(!n.opening && !n.closing && !n.interval_on && !n.interval_15 && !n.interval_30 &&
!n.interval_hour) {
removeNotifications(name, true);
removeNotifications(n.name, true);
} else {
removeNotifications(name, false);
setNotifications("Notifications edited", name, n);
removeNotifications(n.name, false);
setNotifications("Notifications edited", n);
}
}
......@@ -109,42 +78,49 @@ public class NotificationPresenter {
// Removes the Notification settings from SharedPreferences
public void removeNotifications(String name, boolean dismiss) {
// Remove the set Notifications
Set<String> notificationSettingsSet = pref.getStringSet(name+"NotificationSettings", null);
NotificationSettings n = getNotificationSettingsFromSet(notificationSettingsSet);
deleteNotificationsForFacility(name, n);
deleteNotificationsForFacility(name);
// Remove the NotificationSettings
SharedPreferences.Editor editor = pref.edit();
editor.putStringSet(name + "NotificationSettings", null);
editor.apply();
Realm realm = Realm.getDefaultInstance();
realm.executeTransactionAsync((bgRealm) -> {
NotificationSettings results = bgRealm.where(NotificationSettings.class)
.equalTo("name", name)
.findFirst();
if(dismiss) {
Toast.makeText(mNotificationView.getContext(), "Notifications removed",
Toast.LENGTH_SHORT).show();
if(results != null) {
results.deleteFromRealm();
}
}, () -> { // on success
if(dismiss) {
Toast.makeText(mNotificationView.getContext(), "Notifications removed",
Toast.LENGTH_SHORT).show();