diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/BaseWidgetTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/BaseWidgetTest.java index b7c7aaaf..fa9edeb1 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/BaseWidgetTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/BaseWidgetTest.java @@ -1,5 +1,6 @@ package org.andstatus.todoagenda; +import org.andstatus.todoagenda.prefs.InstanceSettings; import org.andstatus.todoagenda.provider.MockCalendarContentProvider; import org.andstatus.todoagenda.widget.LastEntry; import org.joda.time.DateTime; @@ -47,8 +48,12 @@ DateTime dateTime( } protected void playResults(String tag) { - provider.updateAppSettings(); + provider.updateAppSettings(tag); factory.onDataSetChanged(); factory.logWidgetEntries(tag); } + + protected InstanceSettings getSettings() { + return provider.getSettings(); + } } diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/BirthdayTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/BirthdayTest.java index 772ae80d..55a579c2 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/BirthdayTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/BirthdayTest.java @@ -1,10 +1,7 @@ package org.andstatus.todoagenda; -import androidx.test.platform.app.InstrumentationRegistry; - import org.andstatus.todoagenda.prefs.ApplicationPreferences; import org.andstatus.todoagenda.provider.QueryResultsStorage; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.CalendarEntry; import org.joda.time.DateTime; import org.json.JSONException; @@ -22,14 +19,14 @@ public class BirthdayTest extends BaseWidgetTest { @Test public void testBirthdayOneDayOnly() throws IOException, JSONException { - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.birthday); - provider.startEditing(); + provider.startEditingPreferences(); ApplicationPreferences.setEventsEnded(provider.getContext(), EndedSomeTimeAgo.NONE); ApplicationPreferences.setShowPastEventsWithDefaultColor(provider.getContext(), false); ApplicationPreferences.setEventRange(provider.getContext(), 30); - provider.saveSettings(); + provider.savePreferences(); playAtOneTime(inputs, dateTime(2015, 8, 1, 17, 0), 0); playAtOneTime(inputs, dateTime(2015, 8, 9, 23, 59), 0); @@ -46,22 +43,22 @@ public void testBirthdayOneDayOnly() throws IOException, JSONException { playAtOneTime(inputs, dateTime(2015, 9, 10, 11, 0), 0); ApplicationPreferences.setEventsEnded(provider.getContext(), EndedSomeTimeAgo.ONE_HOUR); - provider.saveSettings(); + provider.savePreferences(); playAtOneTime(inputs, dateTime(2015, 9, 10, 0, 30), 2); playAtOneTime(inputs, dateTime(2015, 9, 10, 1, 30), 0); ApplicationPreferences.setEventsEnded(provider.getContext(), EndedSomeTimeAgo.TODAY); - provider.saveSettings(); + provider.savePreferences(); playAtOneTime(inputs, dateTime(2015, 9, 10, 1, 30), 0); ApplicationPreferences.setEventsEnded(provider.getContext(), EndedSomeTimeAgo.FOUR_HOURS); - provider.saveSettings(); + provider.savePreferences(); playAtOneTime(inputs, dateTime(2015, 9, 10, 1, 30), 2); playAtOneTime(inputs, dateTime(2015, 9, 10, 3, 59), 2); playAtOneTime(inputs, dateTime(2015, 9, 10, 4, 0), 0); ApplicationPreferences.setEventsEnded(provider.getContext(), EndedSomeTimeAgo.YESTERDAY); - provider.saveSettings(); + provider.savePreferences(); playAtOneTime(inputs, dateTime(2015, 9, 10, 4, 0), 2); playAtOneTime(inputs, dateTime(2015, 9, 10, 11, 0), 2); playAtOneTime(inputs, dateTime(2015, 9, 10, 17, 0), 2); @@ -70,14 +67,14 @@ public void testBirthdayOneDayOnly() throws IOException, JSONException { playAtOneTime(inputs, dateTime(2015, 9, 11, 0, 30), 0); ApplicationPreferences.setShowPastEventsWithDefaultColor(provider.getContext(), true); - provider.saveSettings(); + provider.savePreferences(); playAtOneTime(inputs, dateTime(2015, 9, 11, 0, 30), 0); } private void playAtOneTime(QueryResultsStorage inputs, DateTime now, int entriesWithoutLastExpected) { provider.clear(); provider.addResults(inputs.getResults()); - DateUtil.setNow(now); + getSettings().clock().setNow(now); EnvironmentChangedReceiver.sleep(MIN_MILLIS_BETWEEN_RELOADS); playResults(TAG); assertEquals(entriesWithoutLastExpected == 0 ? 0 : entriesWithoutLastExpected + 1, diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/DuplicateEventsTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/DuplicateEventsTest.java index de05ea47..a6f6d7a9 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/DuplicateEventsTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/DuplicateEventsTest.java @@ -1,9 +1,5 @@ package org.andstatus.todoagenda; -import android.util.Log; - -import androidx.test.platform.app.InstrumentationRegistry; - import org.andstatus.todoagenda.provider.QueryResultsStorage; import org.json.JSONException; import org.junit.Test; @@ -23,10 +19,9 @@ public class DuplicateEventsTest extends BaseWidgetTest { @Test public void testIssue354() throws IOException, JSONException { final String method = "testIssue354"; - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.duplicates); provider.addResults(inputs.getResults()); - Log.d(method, "Results executed at " + inputs.getResults().get(0).getExecutedAt()); playResults(method); assertEquals("Number of entries", 40, factory.getWidgetEntries().size()); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/IllegalInstantDueToTimeZoneTransitionTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/IllegalInstantDueToTimeZoneTransitionTest.java index 8eced1ea..7703d093 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/IllegalInstantDueToTimeZoneTransitionTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/IllegalInstantDueToTimeZoneTransitionTest.java @@ -4,7 +4,6 @@ import org.andstatus.todoagenda.calendar.CalendarEvent; import org.andstatus.todoagenda.provider.QueryRow; -import org.andstatus.todoagenda.util.DateUtil; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; @@ -43,9 +42,9 @@ public void testIllegalInstantDueToTimeZoneOffsetTransition() { oneTimeDst("2015-10-25T00:00:00+00:00"); oneTimeDst("2011-03-27T00:00:00+00:00"); oneTimeDst("1980-04-06T00:00:00+00:00"); - provider.addRow(new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(),false) - .setStartDate(DateUtil.startOfTomorrow(provider.getSettings().getTimeZone())) + provider.addRow(new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(),false) + .setStartDate(getSettings().clock().startOfTomorrow(getSettings().getTimeZone())) .setEventSource(provider.getFirstActiveEventSource()) .setTitle("This will be the only event that will be shown")); playResults(TAG); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/MultidayAllDayEventTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/MultidayAllDayEventTest.java index e6f83430..a79c6d35 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/MultidayAllDayEventTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/MultidayAllDayEventTest.java @@ -4,7 +4,6 @@ import org.andstatus.todoagenda.prefs.ApplicationPreferences; import org.andstatus.todoagenda.provider.QueryResultsStorage; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.DayHeader; import org.andstatus.todoagenda.widget.LastEntry; import org.andstatus.todoagenda.widget.WidgetEntry; @@ -14,8 +13,6 @@ import java.io.IOException; -import androidx.test.platform.app.InstrumentationRegistry; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -27,16 +24,16 @@ public class MultidayAllDayEventTest extends BaseWidgetTest { @Test public void testInsidePeriod() throws IOException, JSONException { final String method = "testInsidePeriod"; - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.multi_day); provider.addResults(inputs.getResults()); int dateRange = 30; - provider.startEditing(); + provider.startEditingPreferences(); ApplicationPreferences.setEventRange(provider.getContext(), dateRange); - provider.saveSettings(); - DateTime now = new DateTime(2015, 8, 30, 0, 0, 1, 0, provider.getSettings().getTimeZone()); - DateUtil.setNow(now); + provider.savePreferences(); + DateTime now = new DateTime(2015, 8, 30, 0, 0, 1, 0, getSettings().getTimeZone()); + getSettings().clock().setNow(now); playResults(method); DateTime today = now.withTimeAtStartOfDay(); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/MultidayEventTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/MultidayEventTest.java index bc76c9ad..612143cf 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/MultidayEventTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/MultidayEventTest.java @@ -3,7 +3,6 @@ import android.util.Log; import org.andstatus.todoagenda.calendar.CalendarEvent; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.CalendarEntry; import org.andstatus.todoagenda.widget.WidgetEntry; import org.joda.time.DateTime; @@ -30,9 +29,9 @@ public class MultidayEventTest extends BaseWidgetTest { */ @Test public void testEventWhichCarryOverToTheNextDay() { - DateTimeZone timeZone = provider.getSettings().getTimeZone(); - DateTime today = DateUtil.now(timeZone).withTimeAtStartOfDay(); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), + DateTimeZone timeZone = getSettings().getTimeZone(); + DateTime today = getSettings().clock().now(timeZone).withTimeAtStartOfDay(); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), timeZone, false); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); @@ -40,7 +39,7 @@ public void testEventWhichCarryOverToTheNextDay() { event.setStartDate(today.plusHours(19)); event.setEndDate(today.plusDays(1).plusHours(7)); - DateUtil.setNow(today.plusHours(10).plusMinutes(33)); + getSettings().clock().setNow(today.plusHours(10).plusMinutes(33)); provider.addRow(event); playResults(TAG); CalendarEntry entry1 = null; @@ -78,8 +77,8 @@ public void testEventWhichCarryOverToTheNextDay() { public void testThreeDaysEvent() { DateTime friday = dateTime(2015, 9, 18); DateTime sunday = friday.plusDays(2); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), false); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), false); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Leader's weekend"); @@ -102,7 +101,7 @@ private void assertSundayEntryAt(CalendarEvent event, DateTime sunday, DateTime } private CalendarEntry getSundayEntryAt(CalendarEvent event, DateTime currentDateTime) { - DateUtil.setNow(currentDateTime); + getSettings().clock().setNow(currentDateTime); provider.clear(); provider.addRow(event); Log.i(TAG, "getSundayEntryAt " + currentDateTime); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/OngoingEventTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/OngoingEventTest.java index bc7988b9..89b872ca 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/OngoingEventTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/OngoingEventTest.java @@ -1,7 +1,6 @@ package org.andstatus.todoagenda; import org.andstatus.todoagenda.calendar.CalendarEvent; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.CalendarEntry; import org.andstatus.todoagenda.widget.WidgetEntry; import org.joda.time.DateTime; @@ -24,16 +23,16 @@ public class OngoingEventTest extends BaseWidgetTest { */ @Test public void testTodaysOngoingEvent() { - DateTime today = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), false); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), false); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Ongoing event shows original start time"); event.setStartDate(today.plusHours(9)); event.setEndDate(today.plusHours(12)); - DateUtil.setNow(today.plusHours(10).plusMinutes(33)); + getSettings().clock().setNow(today.plusHours(10).plusMinutes(33)); provider.addRow(event); playResults(TAG); CalendarEntry entry = null; @@ -54,16 +53,16 @@ public void testTodaysOngoingEvent() { */ @Test public void testYesterdaysOngoingEvent() { - DateTime today = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), false); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), false); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Ongoing event, which started yesterday, shows no start time"); event.setStartDate(today.minusDays(1).plusHours(9)); event.setEndDate(today.plusHours(12)); - DateUtil.setNow(today.plusHours(10).plusMinutes(33)); + getSettings().clock().setNow(today.plusHours(10).plusMinutes(33)); provider.addRow(event); playResults(TAG); CalendarEntry entry = null; @@ -83,16 +82,16 @@ public void testYesterdaysOngoingEvent() { @Test public void testEventWhichCarryOverToTheNextDay() { - DateTime today = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), false); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), false); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Event that carry over to the next day, show as ending midnight"); event.setStartDate(today.plusHours(19)); event.setEndDate(today.plusDays(1).plusHours(7)); - DateUtil.setNow(today.plusHours(20).plusMinutes(33)); + getSettings().clock().setNow(today.plusHours(20).plusMinutes(33)); provider.addRow(event); playResults(TAG); CalendarEntry entry = null; diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/PastDueHeaderWithTasksTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/PastDueHeaderWithTasksTest.java index 73e15b9a..533c0c8f 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/PastDueHeaderWithTasksTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/PastDueHeaderWithTasksTest.java @@ -1,9 +1,7 @@ package org.andstatus.todoagenda; -import android.util.Log; - import org.andstatus.todoagenda.provider.QueryResultsStorage; -import org.andstatus.todoagenda.util.DateUtil; +import org.andstatus.todoagenda.util.MyClock; import org.andstatus.todoagenda.widget.CalendarEntry; import org.andstatus.todoagenda.widget.LastEntry; import org.andstatus.todoagenda.widget.TaskEntry; @@ -12,8 +10,6 @@ import java.io.IOException; -import androidx.test.platform.app.InstrumentationRegistry; - import static org.junit.Assert.assertEquals; /** @@ -27,13 +23,12 @@ public class PastDueHeaderWithTasksTest extends BaseWidgetTest { @Test public void testPastDueHeaderWithTasks() throws IOException, JSONException { final String method = "testPastDueHeaderWithTasks"; - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.past_due_header_with_tasks); provider.addResults(inputs.getResults()); - Log.d(method, "Results executed at " + inputs.getResults().get(0).getExecutedAt()); playResults(method); - assertEquals("Past and Due header", DateUtil.DATETIME_MIN, factory.getWidgetEntries().get(0).entryDate); + assertEquals("Past and Due header", MyClock.DATETIME_MIN, factory.getWidgetEntries().get(0).entryDate); assertEquals("Past Calendar Entry", CalendarEntry.class, factory.getWidgetEntries().get(1).getClass()); assertEquals("Due task Entry", TaskEntry.class, factory.getWidgetEntries().get(2).getClass()); assertEquals("Due task Entry", dateTime(2019, 8, 1, 9, 0), diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/RecurringEventsTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/RecurringEventsTest.java index c36a78c1..cfb74f2e 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/RecurringEventsTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/RecurringEventsTest.java @@ -2,7 +2,6 @@ import org.andstatus.todoagenda.prefs.ApplicationPreferences; import org.andstatus.todoagenda.provider.QueryRow; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.CalendarEntry; import org.andstatus.todoagenda.widget.WidgetEntry; import org.joda.time.DateTime; @@ -28,9 +27,9 @@ public class RecurringEventsTest extends BaseWidgetTest { public void testShowRecurringEvents() { generateEventInstances(); assertEquals("Entries: " + factory.getWidgetEntries().size(), 15, countCalendarEntries()); - provider.startEditing(); + provider.startEditingPreferences(); ApplicationPreferences.setShowOnlyClosestInstanceOfRecurringEvent(provider.getContext(), true); - provider.saveSettings(); + provider.savePreferences(); generateEventInstances(); assertEquals("Entries: " + factory.getWidgetEntries().size(), 1, countCalendarEntries()); } @@ -48,7 +47,7 @@ int countCalendarEntries() { void generateEventInstances() { EnvironmentChangedReceiver.sleep(MIN_MILLIS_BETWEEN_RELOADS); provider.clear(); - DateTime date = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); + DateTime date = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); long millis = date.getMillis() + TimeUnit.HOURS.toMillis(10); eventId++; for (int ind = 0; ind < 15; ind++) { diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/SingleEventTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/SingleEventTest.java index 688003d3..bae898ec 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/SingleEventTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/SingleEventTest.java @@ -3,7 +3,6 @@ import org.andstatus.todoagenda.calendar.CalendarEvent; import org.andstatus.todoagenda.prefs.OrderedEventSource; import org.andstatus.todoagenda.provider.EventProviderType; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.CalendarEntry; import org.andstatus.todoagenda.widget.WidgetEntry; import org.joda.time.DateTime; @@ -25,10 +24,10 @@ public class SingleEventTest extends BaseWidgetTest { @Test public void testEventAttributes() { - DateTime today = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); - DateUtil.setNow(today.plusHours(10)); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), false); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + getSettings().clock().setNow(today.plusHours(10)); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), false); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Single Event today with all known attributes"); @@ -48,10 +47,10 @@ public void testEventAttributes() { @Test public void testAlldayEventAttributes() { - DateTime today = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); - DateUtil.setNow(today.plusHours(10)); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), true); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + getSettings().clock().setNow(today.plusHours(10)); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), true); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Single AllDay event today with all known attributes"); @@ -69,9 +68,9 @@ public void testAlldayEventAttributes() { @Test public void testAlldayEventMillis() { EnvironmentChangedReceiver.sleep(MIN_MILLIS_BETWEEN_RELOADS); - DateTime today = DateUtil.now(DateTimeZone.UTC).withTimeAtStartOfDay(); - CalendarEvent event = new CalendarEvent(provider.getContext(), provider.getWidgetId(), - provider.getSettings().getTimeZone(), true); + DateTime today = getSettings().clock().now(DateTimeZone.UTC).withTimeAtStartOfDay(); + CalendarEvent event = new CalendarEvent(getSettings(), provider.getContext(), provider.getWidgetId(), + getSettings().getTimeZone(), true); event.setEventSource(provider.getFirstActiveEventSource()); event.setEventId(++eventId); event.setTitle("Single All day event from millis"); @@ -86,12 +85,12 @@ private void assertOneEvent(CalendarEvent event, boolean equal) { provider.addRow(event); playResults(TAG); - assertFalse(provider.getSettings().toString(), - provider.getSettings().getActiveEventSources(EventProviderType.CALENDAR).isEmpty()); + assertFalse(getSettings().toString(), + getSettings().getActiveEventSources(EventProviderType.CALENDAR).isEmpty()); OrderedEventSource source = provider.getFirstActiveEventSource(); assertTrue(source.toString(), source.source.isAvailable); - assertTrue(provider.getSettings().toString(), - provider.getSettings().getActiveEventSource(EventProviderType.CALENDAR, + assertTrue(getSettings().toString(), + getSettings().getActiveEventSource(EventProviderType.CALENDAR, source.source.getId()).source.isAvailable); assertEquals(factory.getWidgetEntries().toString(), 3, factory.getWidgetEntries().size()); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/TasksFilteringAndOrderingTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/TasksFilteringAndOrderingTest.java index 9042151e..5255f5f8 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/TasksFilteringAndOrderingTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/TasksFilteringAndOrderingTest.java @@ -1,9 +1,5 @@ package org.andstatus.todoagenda; -import android.util.Log; - -import androidx.test.platform.app.InstrumentationRegistry; - import org.andstatus.todoagenda.provider.QueryResultsStorage; import org.json.JSONException; import org.junit.Test; @@ -23,10 +19,9 @@ public class TasksFilteringAndOrderingTest extends BaseWidgetTest { @Test public void testNoFilters() throws IOException, JSONException { final String method = "testNoFilters"; - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.filter_tasks_308_no_filters); provider.addResults(inputs.getResults()); - Log.d(method, "Results executed at " + inputs.getResults().get(0).getExecutedAt()); playResults(method); assertEquals("Number of entries", 35, factory.getWidgetEntries().size()); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/TestRunListener.java b/app/src/androidTest/java/org/andstatus/todoagenda/TestRunListener.java index cacc2f6c..03b25f56 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/TestRunListener.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/TestRunListener.java @@ -1,16 +1,10 @@ package org.andstatus.todoagenda; -import android.content.Context; -import android.content.Intent; import android.util.Log; -import androidx.test.platform.app.InstrumentationRegistry; - import org.andstatus.todoagenda.prefs.AllSettings; import org.andstatus.todoagenda.provider.EventProviderType; import org.andstatus.todoagenda.provider.MockCalendarContentProvider; -import org.andstatus.todoagenda.util.DateUtil; -import org.joda.time.DateTimeZone; import org.junit.runner.Description; import org.junit.runner.notification.RunListener; @@ -19,39 +13,27 @@ */ public class TestRunListener extends RunListener { private static final String TAG = "testSuite"; - private final DateTimeZone storedZone; public TestRunListener() { Log.i(TAG, "TestRunListener created"); - storedZone = DateTimeZone.getDefault(); } @Override public void testSuiteFinished(Description description) throws Exception { super.testSuiteFinished(description); Log.i(TAG, "Test Suite finished: " + description); - if (description.toString().equals("null")) restoreWidgets(); + if (description.toString().equals("null")) restoreApp(); } - private void restoreWidgets() { + private void restoreApp() { MockCalendarContentProvider.tearDown(); - DateUtil.setNow(null); - DateTimeZone.setDefault(storedZone); + EnvironmentChangedReceiver.sleep(2000); + AllSettings.forget(); EventProviderType.forget(); EnvironmentChangedReceiver.forget(); - refreshWidgets(); Log.i(TAG, "App restored"); } - - // Context is not exactly what the widgets use normally... - private static void refreshWidgets() { - Intent intent = new Intent(RemoteViewsFactory.ACTION_REFRESH); - InstrumentationRegistry.getInstrumentation().getTargetContext().sendBroadcast(intent); - Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - EnvironmentChangedReceiver.updateAllWidgets(targetContext); - EnvironmentChangedReceiver.sleep(2000); - } } diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/TodaysColorsEventsTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/TodaysColorsEventsTest.java index e95ff699..20463afc 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/TodaysColorsEventsTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/TodaysColorsEventsTest.java @@ -1,15 +1,11 @@ package org.andstatus.todoagenda; -import android.util.Log; - import org.andstatus.todoagenda.provider.QueryResultsStorage; import org.json.JSONException; import org.junit.Test; import java.io.IOException; -import androidx.test.platform.app.InstrumentationRegistry; - import static org.junit.Assert.assertEquals; /** @@ -23,10 +19,9 @@ public class TodaysColorsEventsTest extends BaseWidgetTest { @Test public void testIssue327() throws IOException, JSONException { final String method = "testIssue327"; - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.todays_colors); provider.addResults(inputs.getResults()); - Log.d(method, "Results executed at " + inputs.getResults().get(0).getExecutedAt()); playResults(method); assertEquals("Number of entries", 43, factory.getWidgetEntries().size()); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/WrongDatesLostEventsTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/WrongDatesLostEventsTest.java index 0e931453..778db56b 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/WrongDatesLostEventsTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/WrongDatesLostEventsTest.java @@ -1,9 +1,5 @@ package org.andstatus.todoagenda; -import android.util.Log; - -import androidx.test.platform.app.InstrumentationRegistry; - import org.andstatus.todoagenda.provider.QueryResultsStorage; import org.andstatus.todoagenda.widget.CalendarEntry; import org.json.JSONException; @@ -24,10 +20,9 @@ public class WrongDatesLostEventsTest extends BaseWidgetTest { @Test public void testIssue205() throws IOException, JSONException { final String method = "testIssue205"; - QueryResultsStorage inputs = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.wrong_dates_lost_events); provider.addResults(inputs.getResults()); - Log.d(method, "Results executed at " + inputs.getResults().get(0).getExecutedAt()); playResults(method); assertEquals("Number of entries", 11, factory.getWidgetEntries().size()); diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProvider.java b/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProvider.java index fc117381..d37177dc 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProvider.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProvider.java @@ -5,7 +5,6 @@ import androidx.annotation.NonNull; import androidx.annotation.RawRes; -import androidx.test.core.app.ApplicationProvider; import androidx.test.platform.app.InstrumentationRegistry; import org.andstatus.todoagenda.calendar.CalendarEvent; @@ -15,9 +14,8 @@ import org.andstatus.todoagenda.prefs.OrderedEventSource; import org.andstatus.todoagenda.prefs.SettingsStorage; import org.andstatus.todoagenda.prefs.SnapshotMode; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.util.RawResourceUtils; -import org.joda.time.DateTimeZone; +import org.joda.time.DateTime; import org.json.JSONException; import org.json.JSONObject; @@ -46,10 +44,6 @@ public class MockCalendarContentProvider { private volatile InstanceSettings settings; public static MockCalendarContentProvider getContentProvider() { - DateTimeZone zone = DateTimeZone.forID(ZONE_IDS[(int)(System.currentTimeMillis() % ZONE_IDS.length)]); - DateTimeZone.setDefault(zone); - Log.i(TAG, "Default Time zone set to " + zone); - Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); MockCalendarContentProvider contentProvider = new MockCalendarContentProvider(targetContext); return contentProvider; @@ -61,18 +55,26 @@ private MockCalendarContentProvider(Context context) { .filter(settings -> settings.getWidgetInstanceName().endsWith(InstanceSettings.TEST_REPLAY_SUFFIX)).findFirst().orElse(null); widgetId = instanceToReuse == null ? lastWidgetId.incrementAndGet() : instanceToReuse.getWidgetId(); - settings = new InstanceSettings(context, widgetId, + InstanceSettings settings = new InstanceSettings(context, widgetId, "ToDo Agenda " + widgetId + " " + InstanceSettings.TEST_REPLAY_SUFFIX); + settings.setLockedTimeZoneId(ZONE_IDS[(int)(System.currentTimeMillis() % ZONE_IDS.length)]); + setSettings(settings); + } + + private void setSettings(InstanceSettings settings) { + this.settings = settings; AllSettings.addNew(context, settings); } - public void updateAppSettings() { - InstanceSettings settings = AllSettings.instanceFromId(context, widgetId); + public void updateAppSettings(String tag) { if (!results.getResults().isEmpty()) { settings.setResultsStorage(results); settings.setSnapshotMode(SnapshotMode.SNAPSHOT_TIME); } AllSettings.addNew(context, settings); + if (results.getResults().size() > 0) { + Log.d(tag, "Results executed at " + settings.clock().now(settings.getTimeZone())); + } } public static void tearDown() { @@ -83,24 +85,18 @@ public static void tearDown() { toDelete.add(settings.getWidgetId()); } } + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); for(int widgetId : toDelete) { instances.remove(widgetId); - SettingsStorage.delete(ApplicationProvider.getApplicationContext(), getStorageKey(widgetId)); + SettingsStorage.delete(context, getStorageKey(widgetId)); } - ApplicationPreferences.setWidgetId(ApplicationProvider.getApplicationContext(), TEST_WIDGET_ID_MIN); + ApplicationPreferences.setWidgetId(context, TEST_WIDGET_ID_MIN); } public void addResults(List results) { for (QueryResult result : results) { addResult(result); } - if (!results.isEmpty()) { - Context context = getSettings().getContext(); - int widgetId = getSettings().getWidgetId(); - ApplicationPreferences.fromInstanceSettings(context, widgetId); - ApplicationPreferences.setLockedTimeZoneId(context, results.get(0).getExecutedAt().getZone().getID()); - ApplicationPreferences.save(context, widgetId); - } } public void addResult(QueryResult result) { @@ -126,7 +122,7 @@ public void addRow(QueryRow queryRow) { EventProviderType providerType = EventProviderType.CALENDAR; QueryResult result = results.findLast(providerType).orElseGet( () -> { QueryResult r2 = new QueryResult(providerType, getSettings().getWidgetId(), - DateUtil.now(getSettings().getTimeZone())); + getSettings().clock().now(getSettings().getTimeZone())); results.addResult(r2); return r2; }); @@ -135,7 +131,7 @@ public void addRow(QueryRow queryRow) { @NonNull public InstanceSettings getSettings() { - return AllSettings.instanceFromId(getContext(), getWidgetId()); + return settings; } public void clear() { @@ -146,19 +142,31 @@ public int getWidgetId() { return widgetId; } - public void startEditing() { + public void startEditingPreferences() { ApplicationPreferences.fromInstanceSettings(getContext(), getWidgetId()); } - public void saveSettings() { + public void savePreferences() { ApplicationPreferences.save(getContext(), getWidgetId()); + settings = AllSettings.instanceFromId(getContext(), getWidgetId()); } - public QueryResultsStorage loadResultsAndSettings(Context context, @RawRes int jsonResId) + public QueryResultsStorage loadResultsAndSettings(@RawRes int jsonResId) throws IOException, JSONException { - JSONObject json = new JSONObject(RawResourceUtils.getString(context, jsonResId)); + JSONObject json = new JSONObject(RawResourceUtils.getString(InstrumentationRegistry.getInstrumentation().getContext(), jsonResId)); json.getJSONObject(KEY_SETTINGS).put(PREF_WIDGET_ID, widgetId); - return QueryResultsStorage.fromTestData(getContext(), json); + + WidgetData widgetData = WidgetData.fromJson(json); + // TODO: Map Calendars when moving between devices + InstanceSettings settings = widgetData.getSettings(context, this.settings); + QueryResultsStorage results = QueryResultsStorage.fromJson(widgetId, json); + if (!results.getResults().isEmpty()) { + DateTime now = results.getResults().get(0).getExecutedAt(); + settings.clock().setNow(now); + } + + setSettings(settings); + return results; } public OrderedEventSource getFirstActiveEventSource() { diff --git a/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProviderTest.java b/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProviderTest.java index 81fed171..cec0f021 100644 --- a/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProviderTest.java +++ b/app/src/androidTest/java/org/andstatus/todoagenda/provider/MockCalendarContentProviderTest.java @@ -3,12 +3,9 @@ import android.net.Uri; import android.provider.CalendarContract; -import androidx.test.platform.app.InstrumentationRegistry; - import org.andstatus.todoagenda.BaseWidgetTest; import org.andstatus.todoagenda.calendar.CalendarEventProvider; import org.andstatus.todoagenda.prefs.InstanceSettings; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.util.PermissionsUtil; import org.joda.time.DateTime; import org.json.JSONException; @@ -28,6 +25,7 @@ * @author yvolk@yurivolkov.com */ public class MockCalendarContentProviderTest extends BaseWidgetTest { + private final static String TAG = MockCalendarContentProviderTest.class.getSimpleName(); private final String[] projection = CalendarEventProvider.getProjection(); private final String sortOrder = CalendarEventProvider.EVENT_SORT_ORDER; @@ -53,7 +51,7 @@ public void testTestMode() { public void testTwoEventsToday() { QueryResult input1 = addOneResult(""); QueryResult input2 = addOneResult("SOMETHING=1"); - provider.updateAppSettings(); + provider.updateAppSettings(TAG); QueryResultsStorage.setNeedToStoreResults(true, provider.getWidgetId()); MyContentResolver resolver = new MyContentResolver(EventProviderType.CALENDAR, provider.getContext(), provider.getWidgetId()); @@ -82,9 +80,9 @@ public void testTwoEventsToday() { } private QueryResult addOneResult(String selection) { - QueryResult input = new QueryResult(EventProviderType.CALENDAR, provider.getSettings(), + QueryResult input = new QueryResult(EventProviderType.CALENDAR, getSettings(), CalendarContract.Instances.CONTENT_URI, projection, selection, null, sortOrder); - DateTime today = DateUtil.now(provider.getSettings().getTimeZone()).withTimeAtStartOfDay(); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); input.addRow(new QueryRow().setEventId(++eventId) .setTitle("First Event today").setBegin(today.plusHours(8).getMillis())); input.addRow(new QueryRow() @@ -105,8 +103,7 @@ private QueryResult addOneResult(String selection) { } private QueryResult queryList(MyContentResolver resolver, Uri uri, String selection) { - InstanceSettings settings = provider.getSettings(); - QueryResult result = new QueryResult(EventProviderType.CALENDAR, settings, + QueryResult result = new QueryResult(EventProviderType.CALENDAR, getSettings(), uri, projection, selection, null, sortOrder); result = resolver.foldEvents(uri, projection, selection, null, sortOrder, result, r -> cursor -> { @@ -119,10 +116,10 @@ private QueryResult queryList(MyContentResolver resolver, Uri uri, String select @Test public void testJsonToAndFrom() throws IOException, JSONException { - QueryResultsStorage inputs1 = provider.loadResultsAndSettings(InstrumentationRegistry.getInstrumentation().getContext(), + QueryResultsStorage inputs1 = provider.loadResultsAndSettings( org.andstatus.todoagenda.tests.R.raw.birthday); JSONObject jsonOutput = inputs1.toJson(provider.getContext(), provider.getWidgetId(), true); - QueryResultsStorage inputs2 = QueryResultsStorage.fromTestData(provider.getContext(), jsonOutput); + QueryResultsStorage inputs2 = QueryResultsStorage.fromJson(provider.getWidgetId(), jsonOutput); assertEquals(inputs1, inputs2); } } diff --git a/app/src/main/java/org/andstatus/todoagenda/EnvironmentChangedReceiver.java b/app/src/main/java/org/andstatus/todoagenda/EnvironmentChangedReceiver.java index d8fd03e3..07547bf9 100644 --- a/app/src/main/java/org/andstatus/todoagenda/EnvironmentChangedReceiver.java +++ b/app/src/main/java/org/andstatus/todoagenda/EnvironmentChangedReceiver.java @@ -14,7 +14,6 @@ import org.andstatus.todoagenda.prefs.AllSettings; import org.andstatus.todoagenda.prefs.InstanceSettings; import org.andstatus.todoagenda.provider.EventProviderType; -import org.andstatus.todoagenda.util.DateUtil; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -60,7 +59,7 @@ public static void registerReceivers(Map instances) { private static void scheduleMidnightAlarms(Context context, Map instances) { Set alarmTimes = new HashSet<>(); for (InstanceSettings settings : instances.values()) { - alarmTimes.add(DateUtil.now(settings.getTimeZone()).withTimeAtStartOfDay().plusDays(1)); + alarmTimes.add(settings.clock().now(settings.getTimeZone()).withTimeAtStartOfDay().plusDays(1)); } int counter = 0; for (DateTime alarmTime : alarmTimes) { @@ -78,7 +77,7 @@ private static void scheduleMidnightAlarms(Context context, Map instances) { - DateTime now = DateUtil.now(DateTimeZone.UTC).plusMinutes(1); + DateTime now = DateTime.now(DateTimeZone.UTC).plusMinutes(1); int periodMinutes = (int) TimeUnit.DAYS.toMinutes(1); for (InstanceSettings settings : instances.values()) { int period = settings.getRefreshPeriodMinutes(); diff --git a/app/src/main/java/org/andstatus/todoagenda/RemoteViewsFactory.java b/app/src/main/java/org/andstatus/todoagenda/RemoteViewsFactory.java index 771bfd3f..04aab7c9 100644 --- a/app/src/main/java/org/andstatus/todoagenda/RemoteViewsFactory.java +++ b/app/src/main/java/org/andstatus/todoagenda/RemoteViewsFactory.java @@ -21,6 +21,7 @@ import org.andstatus.todoagenda.provider.EventProviderType; import org.andstatus.todoagenda.util.CalendarIntentUtil; import org.andstatus.todoagenda.util.DateUtil; +import org.andstatus.todoagenda.util.MyClock; import org.andstatus.todoagenda.util.PermissionsUtil; import org.andstatus.todoagenda.widget.DayHeader; import org.andstatus.todoagenda.widget.DayHeaderVisualizer; @@ -73,7 +74,7 @@ public RemoteViewsFactory(Context context, int widgetId) { this.context = context; this.widgetId = widgetId; visualizers.add(new LastEntryVisualizer(context, widgetId)); - widgetEntries.add(new LastEntry(NOT_LOADED, DateUtil.now(getSettings().getTimeZone()))); + widgetEntries.add(new LastEntry(getSettings(), NOT_LOADED, getSettings().clock().now(getSettings().getTimeZone()))); logEvent("Init"); } @@ -193,7 +194,7 @@ private List queryWidgetEntries(InstanceSettings settings) { Collections.sort(eventEntries); List deduplicated = settings.getHideDuplicates() ? hideDuplicates(eventEntries) : eventEntries; List widgetEntries = settings.getShowDayHeaders() ? addDayHeaders(deduplicated) : deduplicated; - LastEntry.addLast(widgetEntries); + LastEntry.addLast(settings, widgetEntries); return widgetEntries; } @@ -219,8 +220,8 @@ private List addDayHeaders(List listIn) { List listOut = new ArrayList<>(); if (!listIn.isEmpty()) { InstanceSettings settings = getSettings(); - DateTime today = DateUtil.now(getSettings().getTimeZone()).withTimeAtStartOfDay(); - DayHeader curDayBucket = new DayHeader(DateUtil.DATETIME_MIN); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + DayHeader curDayBucket = new DayHeader(settings, MyClock.DATETIME_MIN); boolean pastEventsHeaderAdded = false; for (WidgetEntry entry : listIn) { DateTime nextEntryDay = entry.getEntryDay(); @@ -233,7 +234,7 @@ private List addDayHeaders(List listIn) { if (settings.getShowDaysWithoutEvents()) { addEmptyDayHeadersBetweenTwoDays(listOut, curDayBucket.getEntryDay(), nextEntryDay); } - curDayBucket = new DayHeader(nextEntryDay); + curDayBucket = new DayHeader(settings, nextEntryDay); listOut.add(curDayBucket); } listOut.add(entry); @@ -255,12 +256,12 @@ List getWidgetEntries() { private void addEmptyDayHeadersBetweenTwoDays(List entries, DateTime fromDayExclusive, DateTime toDayExclusive) { DateTime emptyDay = fromDayExclusive.plusDays(1); - DateTime today = DateUtil.now(getSettings().getTimeZone()).withTimeAtStartOfDay(); + DateTime today = getSettings().clock().now(getSettings().getTimeZone()).withTimeAtStartOfDay(); if (emptyDay.isBefore(today)) { emptyDay = today; } while (emptyDay.isBefore(toDayExclusive)) { - entries.add(new DayHeader(emptyDay)); + entries.add(new DayHeader(getSettings(), emptyDay)); emptyDay = emptyDay.plusDays(1); } } @@ -319,7 +320,7 @@ private static void configureCurrentDate(InstanceSettings settings, RemoteViews int viewId = R.id.calendar_current_date; rv.setOnClickPendingIntent(viewId, createOpenCalendarPendingIntent(settings)); String formattedDate = settings.getShowDateOnWidgetHeader() - ? DateUtil.createDateString(settings, DateUtil.now(settings.getTimeZone())).toUpperCase(Locale.getDefault()) + ? DateUtil.createDateString(settings, settings.clock().now(settings.getTimeZone())).toUpperCase(Locale.getDefault()) : " "; rv.setTextViewText(viewId, formattedDate); setTextSize(settings, rv, viewId, R.dimen.widget_header_title); diff --git a/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEvent.java b/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEvent.java index d4a49657..e2616f64 100644 --- a/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEvent.java +++ b/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEvent.java @@ -16,6 +16,7 @@ public class CalendarEvent { + private final InstanceSettings settings; private final Context context; private final int widgetId; private final DateTimeZone zone; @@ -32,7 +33,8 @@ public class CalendarEvent { private boolean alarmActive; private boolean recurring; - public CalendarEvent(Context context, int widgetId, DateTimeZone zone, boolean allDay) { + public CalendarEvent(InstanceSettings settings, Context context, int widgetId, DateTimeZone zone, boolean allDay) { + this.settings = settings; this.context = context; this.widgetId = widgetId; this.zone = zone; @@ -235,7 +237,7 @@ public int hashCode() { } public boolean isActive() { - DateTime now = DateUtil.now(zone); + DateTime now = settings.clock().now(zone); return startDate.isBefore(now) && endDate.isAfter(now); } diff --git a/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventProvider.java b/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventProvider.java index 8fdbdcc1..13722749 100644 --- a/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventProvider.java +++ b/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventProvider.java @@ -18,7 +18,6 @@ import org.andstatus.todoagenda.provider.EventProvider; import org.andstatus.todoagenda.provider.EventProviderType; import org.andstatus.todoagenda.util.CalendarIntentUtil; -import org.andstatus.todoagenda.util.DateUtil; import org.joda.time.DateTime; import java.util.ArrayList; @@ -74,9 +73,9 @@ private void filterShowOnlyClosestInstanceOfRecurringEvent(@NonNull List getPastEventsWithColorList() { Uri.Builder builder = Instances.CONTENT_URI.buildUpon(); ContentUris.appendId(builder, 0); - ContentUris.appendId(builder, DateUtil.now(zone).getMillis()); + ContentUris.appendId(builder, getSettings().clock().now(zone).getMillis()); List eventList = queryList(builder.build(), getPastEventsWithColorSelection()); for (CalendarEvent event : eventList) { event.setDefaultCalendarColor(); @@ -203,7 +202,7 @@ private CalendarEvent createCalendarEvent(Cursor cursor) { .getActiveEventSource(type, cursor.getInt(cursor.getColumnIndex(Instances.CALENDAR_ID))); boolean allDay = cursor.getInt(cursor.getColumnIndex(Instances.ALL_DAY)) > 0; - CalendarEvent event = new CalendarEvent(context, widgetId, zone, allDay); + CalendarEvent event = new CalendarEvent(getSettings(), context, widgetId, zone, allDay); event.setEventSource(source); event.setEventId(cursor.getInt(cursor.getColumnIndex(Instances.EVENT_ID))); event.setTitle(cursor.getString(cursor.getColumnIndex(Instances.TITLE))); diff --git a/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventVisualizer.java b/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventVisualizer.java index 948b3cef..1e4734fd 100644 --- a/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventVisualizer.java +++ b/app/src/main/java/org/andstatus/todoagenda/calendar/CalendarEventVisualizer.java @@ -4,12 +4,11 @@ import android.widget.RemoteViews; import org.andstatus.todoagenda.AlarmIndicatorScaled; -import org.andstatus.todoagenda.RecurringIndicatorScaled; import org.andstatus.todoagenda.R; +import org.andstatus.todoagenda.RecurringIndicatorScaled; import org.andstatus.todoagenda.TextShading; import org.andstatus.todoagenda.prefs.TextShadingPref; import org.andstatus.todoagenda.provider.EventProvider; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.widget.CalendarEntry; import org.andstatus.todoagenda.widget.EventEntryLayout; import org.andstatus.todoagenda.widget.WidgetEntry; @@ -122,11 +121,11 @@ private CalendarEntry getDayOneEntry(CalendarEvent event) { firstDate = dayOfStartOfTimeRange; } } - DateTime today = DateUtil.now(event.getStartDate().getZone()).withTimeAtStartOfDay(); + DateTime today = getSettings().clock().now(event.getStartDate().getZone()).withTimeAtStartOfDay(); if (event.isActive() && firstDate.isBefore(today)) { firstDate = today; } - return CalendarEntry.fromEvent(event, firstDate); + return CalendarEntry.fromEvent(getSettings(), event, firstDate); } private void createFollowingEntries(List entryList, CalendarEntry dayOneEntry) { @@ -136,7 +135,7 @@ private void createFollowingEntries(List entryList, CalendarEntry } DateTime thisDay = dayOneEntry.getEntryDay().plusDays(1).withTimeAtStartOfDay(); while (thisDay.isBefore(endDate)) { - CalendarEntry nextEntry = CalendarEntry.fromEvent(dayOneEntry.getEvent(), thisDay); + CalendarEntry nextEntry = CalendarEntry.fromEvent(getSettings(), dayOneEntry.getEvent(), thisDay); entryList.add(nextEntry); thisDay = thisDay.plusDays(1); } diff --git a/app/src/main/java/org/andstatus/todoagenda/prefs/AllSettings.java b/app/src/main/java/org/andstatus/todoagenda/prefs/AllSettings.java index 3dadcb2e..022c3dbb 100644 --- a/app/src/main/java/org/andstatus/todoagenda/prefs/AllSettings.java +++ b/app/src/main/java/org/andstatus/todoagenda/prefs/AllSettings.java @@ -73,8 +73,8 @@ public static void ensureLoadedFromFiles(Context context, boolean reInitialize) for (int widgetId : getWidgetIds(context)) { InstanceSettings settings; try { - settings = InstanceSettings.fromJson(context, getLoadedInstances(), - loadJsonFromFile(context, getStorageKey(widgetId))); + JSONObject json = loadJsonFromFile(context, getStorageKey(widgetId)); + settings = InstanceSettings.fromJson(context, instances.get(widgetId), json); if (settings.widgetId == 0) { newInstance(context, widgetId); } else { @@ -189,7 +189,8 @@ public static void forget() { } public static InstanceSettings restoreWidgetSettings(Activity activity, JSONObject json, int targetWidgetId) { - InstanceSettings settings = WidgetData.fromJson(json).getSettingsForWidget(activity, targetWidgetId); + InstanceSettings settings = WidgetData.fromJson(json) + .getSettingsForWidget(activity, instances.get(targetWidgetId), targetWidgetId); if (settings.isEmpty()) { settings.logMe(TAG, "Skipped restoreWidgetSettings", settings.widgetId); } else { diff --git a/app/src/main/java/org/andstatus/todoagenda/prefs/InstanceSettings.java b/app/src/main/java/org/andstatus/todoagenda/prefs/InstanceSettings.java index 459f0b47..1276720d 100644 --- a/app/src/main/java/org/andstatus/todoagenda/prefs/InstanceSettings.java +++ b/app/src/main/java/org/andstatus/todoagenda/prefs/InstanceSettings.java @@ -16,6 +16,7 @@ import org.andstatus.todoagenda.provider.EventProviderType; import org.andstatus.todoagenda.provider.QueryResultsStorage; import org.andstatus.todoagenda.util.DateUtil; +import org.andstatus.todoagenda.util.MyClock; import org.andstatus.todoagenda.util.StringUtil; import org.andstatus.todoagenda.widget.EventEntryLayout; import org.andstatus.todoagenda.widget.WidgetEntry; @@ -31,7 +32,6 @@ import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -154,9 +154,12 @@ public class InstanceSettings { static final String PREF_ABBREVIATE_DATES = "abbreviateDates"; static final boolean PREF_ABBREVIATE_DATES_DEFAULT = false; private boolean abbreviateDates = PREF_ABBREVIATE_DATES_DEFAULT; + static final String PREF_LOCK_TIME_ZONE = "lockTimeZone"; static final String PREF_LOCKED_TIME_ZONE_ID = "lockedTimeZoneId"; private String lockedTimeZoneId = ""; + private volatile MyClock clock = new MyClock(null); + static final String PREF_SNAPSHOT_MODE = "snapshotMode"; private SnapshotMode snapshotMode = SnapshotMode.defaultValue; public final static String PREF_REFRESH_PERIOD_MINUTES = "refreshPeriodMinutes"; @@ -166,11 +169,10 @@ public class InstanceSettings { static final String PREF_RESULTS_STORAGE = "resultsStorage"; private volatile QueryResultsStorage resultsStorage = null; - public static InstanceSettings fromJson(Context context, Map instances, JSONObject json) { + public static InstanceSettings fromJson(Context context, InstanceSettings storedSettings, JSONObject json) { int widgetId = json.optInt(PREF_WIDGET_ID); String instanceName = json.optString(PREF_WIDGET_INSTANCE_NAME); - InstanceSettings storedSettings = instances.get(widgetId); if (storedSettings != null) { if (storedSettings.getWidgetInstanceName().endsWith(TEST_REPLAY_SUFFIX) && !instanceName.endsWith(TEST_REPLAY_SUFFIX)) { @@ -369,6 +371,7 @@ static InstanceSettings fromApplicationPreferences(Context context, int widgetId if (settingsStored != null) { settings.setResultsStorage(settingsStored.getResultsStorage()); + settings.clock.setNow(settingsStored.clock.now(settingsStored.getTimeZone())); } return settings; } @@ -559,7 +562,7 @@ public boolean getAbbreviateDates() { return abbreviateDates; } - private void setLockedTimeZoneId(String lockedTimeZoneId) { + public void setLockedTimeZoneId(String lockedTimeZoneId) { this.lockedTimeZoneId = DateUtil.validatedTimeZoneId(lockedTimeZoneId); } @@ -567,6 +570,10 @@ public String getLockedTimeZoneId() { return lockedTimeZoneId; } + public MyClock clock() { + return clock; + } + public void setSnapshotMode(SnapshotMode snapshotMode) { this.snapshotMode = snapshotMode; } @@ -594,8 +601,9 @@ public boolean isTimeZoneLocked() { } public DateTimeZone getTimeZone() { - return DateTimeZone.forID(DateUtil.validatedTimeZoneId( - isTimeZoneLocked() ? lockedTimeZoneId : TimeZone.getDefault().getID())); + return isTimeZoneLocked() + ? DateTimeZone.forID(DateUtil.validatedTimeZoneId(lockedTimeZoneId)) + : clock().getZone(DateTimeZone.getDefault()); } public EventEntryLayout getEventEntryLayout() { diff --git a/app/src/main/java/org/andstatus/todoagenda/prefs/OtherPreferencesFragment.java b/app/src/main/java/org/andstatus/todoagenda/prefs/OtherPreferencesFragment.java index c095088b..fe4054dc 100644 --- a/app/src/main/java/org/andstatus/todoagenda/prefs/OtherPreferencesFragment.java +++ b/app/src/main/java/org/andstatus/todoagenda/prefs/OtherPreferencesFragment.java @@ -11,6 +11,7 @@ import org.andstatus.todoagenda.MainActivity; import org.andstatus.todoagenda.R; import org.andstatus.todoagenda.util.DateUtil; +import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import java.util.TimeZone; @@ -45,7 +46,7 @@ private void showLockTimeZone(boolean setAlso) { ApplicationPreferences.getLockedTimeZoneId(getActivity()) : TimeZone.getDefault().getID())); preference.setSummary(String.format( getText(isChecked ? R.string.lock_time_zone_on_desc : R.string.lock_time_zone_off_desc).toString(), - timeZone.getName(DateUtil.now(timeZone).getMillis())) + timeZone.getName(DateTime.now(timeZone).getMillis())) ); } } diff --git a/app/src/main/java/org/andstatus/todoagenda/provider/EventProvider.java b/app/src/main/java/org/andstatus/todoagenda/provider/EventProvider.java index 7e82fb9e..8352b306 100644 --- a/app/src/main/java/org/andstatus/todoagenda/provider/EventProvider.java +++ b/app/src/main/java/org/andstatus/todoagenda/provider/EventProvider.java @@ -9,7 +9,6 @@ import org.andstatus.todoagenda.prefs.FilterMode; import org.andstatus.todoagenda.prefs.InstanceSettings; import org.andstatus.todoagenda.prefs.KeywordsFilter; -import org.andstatus.todoagenda.util.DateUtil; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -55,8 +54,8 @@ public EventProvider(EventProviderType type, Context context, int widgetId) { protected void initialiseParameters() { zone = getSettings().getTimeZone(); mKeywordsFilter = new KeywordsFilter(getSettings().getHideBasedOnKeywords()); - mStartOfTimeRange = getSettings().getEventsEnded().endedAt(DateUtil.now(zone)); - mEndOfTimeRange = getEndOfTimeRange(DateUtil.now(zone)); + mStartOfTimeRange = getSettings().getEventsEnded().endedAt(getSettings().clock().now(zone)); + mEndOfTimeRange = getEndOfTimeRange(getSettings().clock().now(zone)); } private DateTime getEndOfTimeRange(DateTime now) { diff --git a/app/src/main/java/org/andstatus/todoagenda/provider/QueryResult.java b/app/src/main/java/org/andstatus/todoagenda/provider/QueryResult.java index 7494b41b..928aa457 100644 --- a/app/src/main/java/org/andstatus/todoagenda/provider/QueryResult.java +++ b/app/src/main/java/org/andstatus/todoagenda/provider/QueryResult.java @@ -50,7 +50,7 @@ public class QueryResult { public QueryResult(EventProviderType providerType, InstanceSettings settings, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - this(providerType, settings.getWidgetId(), DateUtil.now(settings.getTimeZone())); + this(providerType, settings.getWidgetId(), settings.clock().now(settings.getTimeZone())); this.uri = uri; this.projection = projection; this.selection = selection; diff --git a/app/src/main/java/org/andstatus/todoagenda/provider/QueryResultsStorage.java b/app/src/main/java/org/andstatus/todoagenda/provider/QueryResultsStorage.java index d12ff770..ba370c92 100644 --- a/app/src/main/java/org/andstatus/todoagenda/provider/QueryResultsStorage.java +++ b/app/src/main/java/org/andstatus/todoagenda/provider/QueryResultsStorage.java @@ -9,9 +9,6 @@ import org.andstatus.todoagenda.RemoteViewsFactory; import org.andstatus.todoagenda.prefs.AllSettings; import org.andstatus.todoagenda.prefs.InstanceSettings; -import org.andstatus.todoagenda.util.DateUtil; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -162,21 +159,6 @@ public JSONObject toJson(Context context, int widgetId, boolean withSettings) th return json; } - static QueryResultsStorage fromTestData(Context context, JSONObject json) throws JSONException { - WidgetData widgetData = WidgetData.fromJson(json); - // TODO: Map Calendars when moving between devices - InstanceSettings settings = widgetData.getSettings(context); - if (!settings.isEmpty()) { - AllSettings.getInstances(context).put(settings.getWidgetId(), settings); - } - QueryResultsStorage results = QueryResultsStorage.fromJson(settings.getWidgetId(), json); - if (!results.results.isEmpty()) { - DateTime now = results.results.get(0).getExecutedAt().toDateTime(DateTimeZone.getDefault()); - DateUtil.setNow(now); - } - return results; - } - public static QueryResultsStorage fromJson(int widgetId, JSONObject jsonStorage) throws JSONException { QueryResultsStorage resultsStorage = new QueryResultsStorage(); if (jsonStorage.has(KEY_RESULTS)) { diff --git a/app/src/main/java/org/andstatus/todoagenda/provider/WidgetData.java b/app/src/main/java/org/andstatus/todoagenda/provider/WidgetData.java index f597f03c..b7bf3645 100644 --- a/app/src/main/java/org/andstatus/todoagenda/provider/WidgetData.java +++ b/app/src/main/java/org/andstatus/todoagenda/provider/WidgetData.java @@ -8,7 +8,6 @@ import androidx.annotation.Nullable; -import org.andstatus.todoagenda.prefs.AllSettings; import org.andstatus.todoagenda.prefs.InstanceSettings; import org.json.JSONException; import org.json.JSONObject; @@ -87,7 +86,9 @@ private static JSONObject getAppInfo(Context context) throws JSONException { JSONObject json = new JSONObject(); try { PackageManager pm = context.getPackageManager(); - PackageInfo pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); + Context applicationContext = context.getApplicationContext(); + PackageInfo pi = pm.getPackageInfo( + (applicationContext == null ? context : applicationContext).getPackageName(), 0); json.put(KEY_APP_VERSION_NAME, pi.versionName); json.put(KEY_APP_VERSION_CODE, pi.versionCode); } catch (PackageManager.NameNotFoundException e) { @@ -117,17 +118,17 @@ public String toString() { return TAG + ":" + jsonData; } - public InstanceSettings getSettings(Context context) { - JSONObject jsonSettings = jsonData.optJSONObject(KEY_SETTINGS); - return jsonSettings == null - ? InstanceSettings.EMPTY - : InstanceSettings.fromJson(context, AllSettings.getLoadedInstances(), jsonSettings); - } - - public InstanceSettings getSettingsForWidget(Context context, int targetWidgetId) { - InstanceSettings inputSettings = getSettings(context); + public InstanceSettings getSettingsForWidget(Context context, InstanceSettings storedSettings, int targetWidgetId) { + InstanceSettings inputSettings = getSettings(context, storedSettings); return inputSettings.isEmpty() ? InstanceSettings.EMPTY : inputSettings.asForWidget(context, targetWidgetId); } + + public InstanceSettings getSettings(Context context, InstanceSettings storedSettings) { + JSONObject jsonSettings = jsonData.optJSONObject(KEY_SETTINGS); + return jsonSettings == null + ? InstanceSettings.EMPTY + : InstanceSettings.fromJson(context, storedSettings, jsonSettings); + } } diff --git a/app/src/main/java/org/andstatus/todoagenda/task/AbstractTaskProvider.java b/app/src/main/java/org/andstatus/todoagenda/task/AbstractTaskProvider.java index b0640fb6..8a45230b 100644 --- a/app/src/main/java/org/andstatus/todoagenda/task/AbstractTaskProvider.java +++ b/app/src/main/java/org/andstatus/todoagenda/task/AbstractTaskProvider.java @@ -6,8 +6,6 @@ import org.andstatus.todoagenda.prefs.FilterMode; import org.andstatus.todoagenda.provider.EventProvider; import org.andstatus.todoagenda.provider.EventProviderType; -import org.andstatus.todoagenda.util.DateUtil; -import org.andstatus.todoagenda.util.PermissionsUtil; import org.joda.time.DateTime; import java.util.Collections; @@ -25,7 +23,7 @@ public AbstractTaskProvider(EventProviderType type, Context context, int widgetI protected void initialiseParameters() { super.initialiseParameters(); - now = DateUtil.now(zone); + now = getSettings().clock().now(zone); } List queryEvents() { diff --git a/app/src/main/java/org/andstatus/todoagenda/task/TaskEvent.java b/app/src/main/java/org/andstatus/todoagenda/task/TaskEvent.java index 037f510e..95299e4b 100644 --- a/app/src/main/java/org/andstatus/todoagenda/task/TaskEvent.java +++ b/app/src/main/java/org/andstatus/todoagenda/task/TaskEvent.java @@ -1,7 +1,7 @@ package org.andstatus.todoagenda.task; +import org.andstatus.todoagenda.prefs.InstanceSettings; import org.andstatus.todoagenda.prefs.OrderedEventSource; -import org.andstatus.todoagenda.util.DateUtil; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -12,13 +12,15 @@ public class TaskEvent { private OrderedEventSource eventSource; private long id; private String title = ""; + private final InstanceSettings settings; private final DateTimeZone zone; private DateTime startDate; private DateTime dueDate; private int color; private TaskStatus status = TaskStatus.UNKNOWN; - public TaskEvent(DateTimeZone zone) { + public TaskEvent(InstanceSettings settings, DateTimeZone zone) { + this.settings = settings; this.zone = zone; } @@ -76,7 +78,7 @@ private DateTime toStartDate(Long startMillis, Long dueMillis) { if (dueMillis != null) { startDate = new DateTime(dueMillis, zone); } else { - startDate = DateUtil.now(zone).withTimeAtStartOfDay(); + startDate = settings.clock().now(zone).withTimeAtStartOfDay(); } } return startDate; @@ -84,7 +86,7 @@ private DateTime toStartDate(Long startMillis, Long dueMillis) { private DateTime toDueDate(Long startMillis, Long dueMillis) { DateTime dueDate = dueMillis == null - ? DateUtil.startOfTomorrow(zone) + ? settings.clock().startOfTomorrow(zone) : new DateTime(dueMillis, zone); return startMillis == null ? dueDate.plusSeconds(1) diff --git a/app/src/main/java/org/andstatus/todoagenda/task/TaskVisualizer.java b/app/src/main/java/org/andstatus/todoagenda/task/TaskVisualizer.java index 7ea9af73..559d0447 100644 --- a/app/src/main/java/org/andstatus/todoagenda/task/TaskVisualizer.java +++ b/app/src/main/java/org/andstatus/todoagenda/task/TaskVisualizer.java @@ -103,7 +103,7 @@ public List queryEventEntries() { private List createEntryList(List events) { List entries = new ArrayList<>(); for (TaskEvent event : events) { - entries.add(TaskEntry.fromEvent(event)); + entries.add(TaskEntry.fromEvent(getSettings(), event)); } return entries; } diff --git a/app/src/main/java/org/andstatus/todoagenda/task/dmfs/DmfsOpenTasksProvider.java b/app/src/main/java/org/andstatus/todoagenda/task/dmfs/DmfsOpenTasksProvider.java index 51060e2f..58152df8 100644 --- a/app/src/main/java/org/andstatus/todoagenda/task/dmfs/DmfsOpenTasksProvider.java +++ b/app/src/main/java/org/andstatus/todoagenda/task/dmfs/DmfsOpenTasksProvider.java @@ -95,7 +95,7 @@ private TaskEvent createTask(Cursor cursor) { OrderedEventSource source = getSettings() .getActiveEventSource(type, cursor.getInt(cursor.getColumnIndex(DmfsOpenTasksContract.Tasks.COLUMN_LIST_ID))); - TaskEvent task = new TaskEvent(zone); + TaskEvent task = new TaskEvent(getSettings(), zone); task.setEventSource(source); task.setId(cursor.getLong(cursor.getColumnIndex(DmfsOpenTasksContract.Tasks.COLUMN_ID))); task.setTitle(cursor.getString(cursor.getColumnIndex(DmfsOpenTasksContract.Tasks.COLUMN_TITLE))); diff --git a/app/src/main/java/org/andstatus/todoagenda/task/samsung/SamsungTasksProvider.java b/app/src/main/java/org/andstatus/todoagenda/task/samsung/SamsungTasksProvider.java index 41a13072..d9dcb0e0 100644 --- a/app/src/main/java/org/andstatus/todoagenda/task/samsung/SamsungTasksProvider.java +++ b/app/src/main/java/org/andstatus/todoagenda/task/samsung/SamsungTasksProvider.java @@ -82,7 +82,7 @@ private TaskEvent createTask(Cursor cursor) { OrderedEventSource source = getSettings() .getActiveEventSource(type, cursor.getInt(cursor.getColumnIndex(SamsungTasksContract.Tasks.COLUMN_LIST_ID))); - TaskEvent task = new TaskEvent(zone); + TaskEvent task = new TaskEvent(getSettings(), zone); task.setEventSource(source); task.setId(cursor.getLong(cursor.getColumnIndex(SamsungTasksContract.Tasks.COLUMN_ID))); task.setTitle(cursor.getString(cursor.getColumnIndex(SamsungTasksContract.Tasks.COLUMN_TITLE))); diff --git a/app/src/main/java/org/andstatus/todoagenda/util/DateUtil.java b/app/src/main/java/org/andstatus/todoagenda/util/DateUtil.java index 58f2c3a9..5fb3fdbf 100644 --- a/app/src/main/java/org/andstatus/todoagenda/util/DateUtil.java +++ b/app/src/main/java/org/andstatus/todoagenda/util/DateUtil.java @@ -20,12 +20,7 @@ import java.util.Locale; public class DateUtil { - private static final String COMMA_SPACE = ", "; - private static volatile DateTime mNow = null; - private static volatile DateTime mNowSetAt = DateTime.now(); - public static final DateTime DATETIME_MIN = new DateTime(0, DateTimeZone.UTC); - public static final DateTime DATETIME_MAX = new DateTime(Long.MAX_VALUE, DateTimeZone.UTC); public static boolean isMidnight(DateTime date) { return date.isEqual(date.withTimeAtStartOfDay()); @@ -88,57 +83,6 @@ public static CharSequence getDaysFromTodayString(Context context, int daysFromT } } - public static boolean isToday(@Nullable DateTime date) { - return isDateDefined(date) && !isBeforeToday(date) && date.isBefore(DateUtil.now(date.getZone()).plusDays(1).withTimeAtStartOfDay()); - } - - public static boolean isBeforeToday(@Nullable DateTime date) { - return isDateDefined(date) && date.isBefore(DateUtil.now(date.getZone()).withTimeAtStartOfDay()); - } - - public static boolean isAfterToday(@Nullable DateTime date) { - return isDateDefined(date) && !date.isBefore(DateUtil.now(date.getZone()).withTimeAtStartOfDay().plusDays(1)); - } - - public static boolean isBeforeNow(@Nullable DateTime date) { - return isDateDefined(date) && date.isBefore(now(date.getZone())); - } - - public static DateTime startOfTomorrow(DateTimeZone zone) { - return startOfNextDay(DateUtil.now(zone)); - } - - public static DateTime startOfNextDay(DateTime date) { - return date.plusDays(1).withTimeAtStartOfDay(); - } - - public static void setNow(DateTime now) { - mNowSetAt = DateTime.now(); - mNow = now; - } - - /** - * Usually returns real "now", but may be #setNow to some other time for testing purposes - */ - public static DateTime now(DateTimeZone zone) { - DateTime nowSetAt; - DateTime now; - do { - nowSetAt = mNowSetAt; - now = mNow; - } while (nowSetAt != mNowSetAt); // Ensure concurrent consistency - if (now == null) { - return DateTime.now(zone); - } else { - long diffL = DateTime.now().getMillis() - nowSetAt.getMillis(); - int diff = 0; - if (diffL > 0 && diffL < Integer.MAX_VALUE) { - diff = (int) diffL; - } - return new DateTime(now, zone).plusMillis(diff); - } - } - /** * Returns an empty string in a case supplied ID is not a valid Time Zone ID */ @@ -182,8 +126,4 @@ public static boolean isSameDay(@Nullable DateTime date, @Nullable DateTime othe return date.year().equals(other.year()) && date.dayOfYear().equals(other.dayOfYear()); } - - public static boolean isDateDefined(@Nullable DateTime dateTime) { - return dateTime != null && dateTime.isAfter(DATETIME_MIN) && dateTime.isBefore(DATETIME_MAX); - } } diff --git a/app/src/main/java/org/andstatus/todoagenda/util/MyClock.java b/app/src/main/java/org/andstatus/todoagenda/util/MyClock.java new file mode 100644 index 00000000..97aa1308 --- /dev/null +++ b/app/src/main/java/org/andstatus/todoagenda/util/MyClock.java @@ -0,0 +1,83 @@ +package org.andstatus.todoagenda.util; + +import androidx.annotation.Nullable; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; + +/** + * A clock, the can be changed independently from a Device clock + * @author yvolk@yurivolkov.com + */ +public class MyClock { + public static final DateTime DATETIME_MIN = new DateTime(0, DateTimeZone.UTC); + public static final DateTime DATETIME_MAX = new DateTime(Long.MAX_VALUE, DateTimeZone.UTC); + + private final DateTimeZone zone; + private volatile DateTime mNow = null; + private volatile DateTime mNowSetAt = DateTime.now(); + + public MyClock(DateTimeZone zone) { + this.zone = zone; + } + + public void setNow(DateTime now) { + mNowSetAt = DateTime.now(); + mNow = now; + } + + /** + * Usually returns real "now", but may be #setNow to some other time for testing purposes + */ + public DateTime now(DateTimeZone zone) { + DateTime nowSetAt; + DateTime now; + do { + nowSetAt = mNowSetAt; + now = mNow; + } while (nowSetAt != mNowSetAt); // Ensure concurrent consistency + if (now == null) { + return DateTime.now(zone); + } else { + long diffL = DateTime.now().getMillis() - nowSetAt.getMillis(); + int diff = 0; + if (diffL > 0 && diffL < Integer.MAX_VALUE) { + diff = (int) diffL; + } + return new DateTime(now, zone).plusMillis(diff); + } + } + + public DateTimeZone getZone(DateTimeZone defaultValue) { + DateTime now = mNow; + return now == null ? defaultValue : now.getZone(); + } + + public boolean isToday(@Nullable DateTime date) { + return isDateDefined(date) && !isBeforeToday(date) && date.isBefore(now(date.getZone()).plusDays(1).withTimeAtStartOfDay()); + } + + public boolean isBeforeToday(@Nullable DateTime date) { + return isDateDefined(date) && date.isBefore(now(date.getZone()).withTimeAtStartOfDay()); + } + + public boolean isAfterToday(@Nullable DateTime date) { + return isDateDefined(date) && !date.isBefore(now(date.getZone()).withTimeAtStartOfDay().plusDays(1)); + } + + public boolean isBeforeNow(@Nullable DateTime date) { + return isDateDefined(date) && date.isBefore(now(date.getZone())); + } + + public DateTime startOfTomorrow(DateTimeZone zone) { + return startOfNextDay(now(zone)); + } + + public static DateTime startOfNextDay(DateTime date) { + return date.plusDays(1).withTimeAtStartOfDay(); + } + + public static boolean isDateDefined(@Nullable DateTime dateTime) { + return dateTime != null && dateTime.isAfter(DATETIME_MIN) && dateTime.isBefore(DATETIME_MAX); + } +} diff --git a/app/src/main/java/org/andstatus/todoagenda/widget/CalendarEntry.java b/app/src/main/java/org/andstatus/todoagenda/widget/CalendarEntry.java index 888055c8..b490337c 100644 --- a/app/src/main/java/org/andstatus/todoagenda/widget/CalendarEntry.java +++ b/app/src/main/java/org/andstatus/todoagenda/widget/CalendarEntry.java @@ -14,7 +14,7 @@ import org.andstatus.todoagenda.util.DateUtil; import org.joda.time.DateTime; -import static org.andstatus.todoagenda.util.DateUtil.isDateDefined; +import static org.andstatus.todoagenda.util.MyClock.isDateDefined; public class CalendarEntry extends WidgetEntry { @@ -28,15 +28,15 @@ public class CalendarEntry extends WidgetEntry { private boolean allDay; private CalendarEvent event; - public static CalendarEntry fromEvent(CalendarEvent event, DateTime entryDate) { - CalendarEntry entry = new CalendarEntry(entryDate); + public static CalendarEntry fromEvent(InstanceSettings settings, CalendarEvent event, DateTime entryDate) { + CalendarEntry entry = new CalendarEntry(settings, entryDate); entry.allDay = event.isAllDay(); entry.event = event; return entry; } - private CalendarEntry(DateTime entryDate) { - super(WidgetEntryPosition.ENTRY_DATE, entryDate); + private CalendarEntry(InstanceSettings settings, DateTime entryDate) { + super(settings, WidgetEntryPosition.ENTRY_DATE, entryDate); } @Nullable diff --git a/app/src/main/java/org/andstatus/todoagenda/widget/DayHeader.java b/app/src/main/java/org/andstatus/todoagenda/widget/DayHeader.java index f1070b5b..83645778 100644 --- a/app/src/main/java/org/andstatus/todoagenda/widget/DayHeader.java +++ b/app/src/main/java/org/andstatus/todoagenda/widget/DayHeader.java @@ -1,12 +1,13 @@ package org.andstatus.todoagenda.widget; +import org.andstatus.todoagenda.prefs.InstanceSettings; import org.joda.time.DateTime; import static org.andstatus.todoagenda.widget.WidgetEntryPosition.DAY_HEADER; public class DayHeader extends WidgetEntry { - public DayHeader(DateTime date) { - super(DAY_HEADER, date); + public DayHeader(InstanceSettings settings, DateTime date) { + super(settings, DAY_HEADER, date); } } diff --git a/app/src/main/java/org/andstatus/todoagenda/widget/LastEntry.java b/app/src/main/java/org/andstatus/todoagenda/widget/LastEntry.java index 8bc028f4..49f6b865 100644 --- a/app/src/main/java/org/andstatus/todoagenda/widget/LastEntry.java +++ b/app/src/main/java/org/andstatus/todoagenda/widget/LastEntry.java @@ -2,7 +2,6 @@ import org.andstatus.todoagenda.R; import org.andstatus.todoagenda.prefs.InstanceSettings; -import org.andstatus.todoagenda.util.DateUtil; import org.andstatus.todoagenda.util.PermissionsUtil; import org.joda.time.DateTime; @@ -19,12 +18,12 @@ public static LastEntry forEmptyList(InstanceSettings settings) { LastEntry.LastEntryType entryType = PermissionsUtil.arePermissionsGranted(settings.getContext()) ? EMPTY : NO_PERMISSIONS; - return new LastEntry(entryType, DateUtil.now(settings.getTimeZone())); + return new LastEntry(settings, entryType, settings.clock().now(settings.getTimeZone())); } - public static void addLast(List widgetEntries) { + public static void addLast(InstanceSettings settings, List widgetEntries) { if (!widgetEntries.isEmpty()) { - LastEntry entry = new LastEntry(LastEntryType.LAST, widgetEntries.get(widgetEntries.size() - 1).entryDate); + LastEntry entry = new LastEntry(settings, LastEntryType.LAST, widgetEntries.get(widgetEntries.size() - 1).entryDate); widgetEntries.add(entry); } } @@ -44,8 +43,8 @@ public enum LastEntryType { public final LastEntryType type; - public LastEntry(LastEntryType type, DateTime date) { - super(LIST_FOOTER, date); + public LastEntry(InstanceSettings settings, LastEntryType type, DateTime date) { + super(settings, LIST_FOOTER, date); this.type = type; } } \ No newline at end of file diff --git a/app/src/main/java/org/andstatus/todoagenda/widget/TaskEntry.java b/app/src/main/java/org/andstatus/todoagenda/widget/TaskEntry.java index d144a52e..b9f27366 100644 --- a/app/src/main/java/org/andstatus/todoagenda/widget/TaskEntry.java +++ b/app/src/main/java/org/andstatus/todoagenda/widget/TaskEntry.java @@ -2,6 +2,7 @@ import androidx.annotation.Nullable; +import org.andstatus.todoagenda.prefs.InstanceSettings; import org.andstatus.todoagenda.prefs.OrderedEventSource; import org.andstatus.todoagenda.task.TaskEvent; import org.joda.time.DateTime; @@ -11,14 +12,14 @@ public class TaskEntry extends WidgetEntry { private TaskEvent event; - public static TaskEntry fromEvent(TaskEvent event) { - TaskEntry entry = new TaskEntry(ENTRY_DATE, event.getStartDate()); + public static TaskEntry fromEvent(InstanceSettings settings, TaskEvent event) { + TaskEntry entry = new TaskEntry(settings, ENTRY_DATE, event.getStartDate()); entry.event = event; return entry; } - private TaskEntry(WidgetEntryPosition entryPosition, DateTime entryDate) { - super(entryPosition, entryDate); + private TaskEntry(InstanceSettings settings, WidgetEntryPosition entryPosition, DateTime entryDate) { + super(settings, entryPosition, entryDate); } @Nullable diff --git a/app/src/main/java/org/andstatus/todoagenda/widget/WidgetEntry.java b/app/src/main/java/org/andstatus/todoagenda/widget/WidgetEntry.java index be3b14b8..c3f6d495 100644 --- a/app/src/main/java/org/andstatus/todoagenda/widget/WidgetEntry.java +++ b/app/src/main/java/org/andstatus/todoagenda/widget/WidgetEntry.java @@ -2,8 +2,10 @@ import androidx.annotation.Nullable; +import org.andstatus.todoagenda.prefs.InstanceSettings; import org.andstatus.todoagenda.prefs.OrderedEventSource; import org.andstatus.todoagenda.util.DateUtil; +import org.andstatus.todoagenda.util.MyClock; import org.joda.time.DateTime; import org.joda.time.Days; @@ -13,38 +15,40 @@ public abstract class WidgetEntry> implements Comparabl public final WidgetEntryPosition entryPosition; public final DateTime entryDate; + protected final InstanceSettings settings; - protected WidgetEntry(WidgetEntryPosition entryPosition, DateTime entryDate) { + protected WidgetEntry(InstanceSettings settings, WidgetEntryPosition entryPosition, DateTime entryDate) { + this.settings = settings; this.entryPosition = entryPosition; this.entryDate = fixEntryDate(entryPosition, entryDate); } - private static DateTime fixEntryDate(WidgetEntryPosition entryPosition, DateTime entryDate) { + private DateTime fixEntryDate(WidgetEntryPosition entryPosition, DateTime entryDate) { switch (entryPosition) { case ENTRY_DATE: throwIfNull(entryPosition, entryDate); return entryDate; case PAST_AND_DUE_HEADER: return entryDate == null - ? DateUtil.DATETIME_MIN + ? MyClock.DATETIME_MIN : entryDate; case DAY_HEADER: case START_OF_DAY: throwIfNull(entryPosition, entryDate); return entryDate.withTimeAtStartOfDay(); case START_OF_TODAY: - return DateUtil.isToday(entryDate) + return settings.clock().isToday(entryDate) ? entryDate - : DateUtil.DATETIME_MIN; + : MyClock.DATETIME_MIN; case END_OF_TODAY: - return DateUtil.isToday(entryDate) + return settings.clock().isToday(entryDate) ? entryDate - : DateUtil.DATETIME_MAX; + : MyClock.DATETIME_MAX; case END_OF_LIST_HEADER: case END_OF_LIST: case LIST_FOOTER: return entryDate == null - ? DateUtil.DATETIME_MAX + ? MyClock.DATETIME_MAX : entryDate; default: throw new IllegalArgumentException("Invalid position " + entryPosition + "; entryDate: " + entryDate); @@ -60,7 +64,7 @@ private static void throwIfNull(WidgetEntryPosition entryPosition, DateTime entr public boolean isLastEntryOfEvent() { return getEndDate() == null || !entryPosition.entryDateIsRequired || - getEndDate().isBefore(DateUtil.startOfNextDay(this.entryDate)); + getEndDate().isBefore(MyClock.startOfNextDay(this.entryDate)); } public DateTime getEntryDay() { @@ -85,7 +89,7 @@ public String getLocation() { } public int getDaysFromToday() { - return Days.daysBetween(DateUtil.now(entryDate.getZone()).withTimeAtStartOfDay(), + return Days.daysBetween(settings.clock().now(entryDate.getZone()).withTimeAtStartOfDay(), entryDate.withTimeAtStartOfDay()).getDays(); } @@ -122,21 +126,21 @@ public TimeSection getTimeSection() { default: break; } - if (DateUtil.isToday(entryDate)) { + if (settings.clock().isToday(entryDate)) { switch (entryPosition) { case DAY_HEADER: return TimeSection.TODAY; default: - if (DateUtil.isToday(getEndDate())) { - return DateUtil.isBeforeNow(getEndDate()) + if (settings.clock().isToday(getEndDate())) { + return settings.clock().isBeforeNow(getEndDate()) ? TimeSection.PAST : TimeSection.TODAY; } } } - return DateUtil.isBeforeToday(entryDate) + return settings.clock().isBeforeToday(entryDate) ? TimeSection.PAST - : (DateUtil.isToday(getEndDate()) ? TimeSection.TODAY : TimeSection.FUTURE); + : (settings.clock().isToday(getEndDate()) ? TimeSection.TODAY : TimeSection.FUTURE); } public boolean duplicates(WidgetEntry other) { @@ -150,8 +154,8 @@ public boolean duplicates(WidgetEntry other) { @Override public String toString() { return entryPosition.value + " [entryDate=" + - (entryDate == DateUtil.DATETIME_MIN ? "min" : - (entryDate == DateUtil.DATETIME_MAX) ? "max" : entryDate) + + (entryDate == MyClock.DATETIME_MIN ? "min" : + (entryDate == MyClock.DATETIME_MAX) ? "max" : entryDate) + "]"; } }