Makes spinner timing configurable by host.
PiperOrigin-RevId: 250570958
Change-Id: I9ed5ffb8b1a6bbb76ca2778c8a89a2b384140b76
diff --git a/src/main/java/com/google/android/libraries/feed/api/host/config/Configuration.java b/src/main/java/com/google/android/libraries/feed/api/host/config/Configuration.java
index 595cc1b..ff510c7 100644
--- a/src/main/java/com/google/android/libraries/feed/api/host/config/Configuration.java
+++ b/src/main/java/com/google/android/libraries/feed/api/host/config/Configuration.java
@@ -77,6 +77,12 @@
ConfigKey.SESSION_LIFETIME_MS,
// Boolean which if true, will ask the server for a snippet from the article.
ConfigKey.SNIPPETS_ENABLED,
+ // Delay before a spinner should be shown after content is requested. Only used for feed wide
+ // spinners, not for more button spinners.
+ ConfigKey.SPINNER_DELAY_MS,
+ // Minimum time before a spinner should show before disappearing. Only used for feed wide
+ // spinners, not for more button spinners.
+ ConfigKey.SPINNER_MINIMUM_SHOW_TIME_MS,
// Time in ms for the length of the timeout
ConfigKey.TIMEOUT_TIMEOUT_MS,
ConfigKey.TRIGGER_IMMEDIATE_PAGINATION,
@@ -127,6 +133,8 @@
String NON_CACHED_PAGE_SIZE = "non_cached_page_size";
String SESSION_LIFETIME_MS = "session_lifetime_ms";
String SNIPPETS_ENABLED = "snippets_enabled";
+ String SPINNER_DELAY_MS = "spinner_delay";
+ String SPINNER_MINIMUM_SHOW_TIME_MS = "spinner_minimum_show_time";
String TIMEOUT_TIMEOUT_MS = "timeout_timeout_ms";
String TRIGGER_IMMEDIATE_PAGINATION = "trigger_immediate_pagination_bool";
String UNDOABLE_ACTIONS_ENABLED = "undoable_actions_enabled";
diff --git a/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java b/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java
index 997bde9..32bc464 100644
--- a/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java
+++ b/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java
@@ -101,9 +101,9 @@
private static final String TAG = "BasicStream";
@VisibleForTesting static final String KEY_STREAM_STATE = "stream-state";
- @VisibleForTesting static final long DEFAULT_LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS = 1000L;
- @VisibleForTesting static final long MINIMUM_SPINNER_SHOW_TIME = 500L;
- @VisibleForTesting static final long MINIMUM_TIME_BEFORE_SHOWING_SPINNER = 500L;
+ private static final long DEFAULT_LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS = 1000L;
+ private static final long DEFAULT_MINIMUM_SPINNER_SHOW_TIME_MS = 500L;
+ private static final long DEFAULT_SPINNER_DELAY_TIME_MS = 500L;
private final CardConfiguration cardConfiguration;
private final Clock clock;
@@ -128,6 +128,8 @@
private final UiSessionRequestLogger uiSessionRequestLogger;
private final StreamConfiguration streamConfiguration;
private final BasicStreamScrollMonitor scrollMonitor;
+ private final long minimumSpinnerShowTime;
+ private final long spinnerDelayTime;
private RecyclerView recyclerView;
private ContextMenuManager contextMenuManager;
@@ -218,6 +220,11 @@
this.context =
new ContextThemeWrapper(context, (isBackgroundDark ? R.style.Dark : R.style.Light));
this.scrollMonitor = new BasicStreamScrollMonitor(clock);
+ this.minimumSpinnerShowTime =
+ configuration.getValueOrDefault(
+ ConfigKey.SPINNER_MINIMUM_SHOW_TIME_MS, DEFAULT_MINIMUM_SPINNER_SHOW_TIME_MS);
+ this.spinnerDelayTime =
+ configuration.getValueOrDefault(ConfigKey.SPINNER_DELAY_MS, DEFAULT_SPINNER_DELAY_TIME_MS);
}
@VisibleForTesting
@@ -638,7 +645,7 @@
if (isInitialLoad && initialLoadingSpinnerStartTime != 0L) {
long spinnerDisplayTime = clock.currentTimeMillis() - initialLoadingSpinnerStartTime;
// If MINIMUM_SPINNER_SHOW_TIME has elapsed, the new content can be shown immediately.
- if (spinnerDisplayTime >= MINIMUM_SPINNER_SHOW_TIME) {
+ if (spinnerDisplayTime >= minimumSpinnerShowTime) {
updateAdapterAfterSessionStart(localModelProvider);
} else {
// If MINIMUM_SPINNER_SHOW_TIME has not elapsed, the new content should only be shown once
@@ -652,7 +659,7 @@
updateAdapterAfterSessionStart(localModelProvider);
}
},
- MINIMUM_SPINNER_SHOW_TIME - spinnerDisplayTime);
+ minimumSpinnerShowTime - spinnerDisplayTime);
}
} else {
updateAdapterAfterSessionStart(localModelProvider);
@@ -800,7 +807,7 @@
private void showSpinnerWithDelay() {
cancellableShowSpinnerRunnable =
mainThreadRunner.executeWithDelay(
- TAG + " onShow", new ShowSpinnerRunnable(), MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ TAG + " onShow", new ShowSpinnerRunnable(), spinnerDelayTime);
}
private String convertStreamSavedInstanceStateToString(
diff --git a/src/test/java/com/google/android/libraries/feed/basicstream/BasicStreamTest.java b/src/test/java/com/google/android/libraries/feed/basicstream/BasicStreamTest.java
index 9a896c4..d75057b 100644
--- a/src/test/java/com/google/android/libraries/feed/basicstream/BasicStreamTest.java
+++ b/src/test/java/com/google/android/libraries/feed/basicstream/BasicStreamTest.java
@@ -16,8 +16,6 @@
import static com.google.android.libraries.feed.api.client.stream.Stream.POSITION_NOT_KNOWN;
import static com.google.android.libraries.feed.basicstream.BasicStream.KEY_STREAM_STATE;
-import static com.google.android.libraries.feed.basicstream.BasicStream.MINIMUM_SPINNER_SHOW_TIME;
-import static com.google.android.libraries.feed.basicstream.BasicStream.MINIMUM_TIME_BEFORE_SHOWING_SPINNER;
import static com.google.android.libraries.feed.common.testing.RunnableSubject.assertThatRunnable;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -134,11 +132,15 @@
.setSessionId(SESSION_ID)
.setScrollState(SCROLL_STATE)
.build();
+ private static final long SPINNER_DELAY_MS = 123L;
+ private static final long SPINNER_MINIMUM_SHOW_TIME_MS = 655L;
private static final Configuration CONFIGURATION =
new Configuration.Builder()
.put(
ConfigKey.LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS,
LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS)
+ .put(ConfigKey.SPINNER_DELAY_MS, SPINNER_DELAY_MS)
+ .put(ConfigKey.SPINNER_MINIMUM_SHOW_TIME_MS, SPINNER_MINIMUM_SHOW_TIME_MS)
.build();
@Mock private StreamConfiguration streamConfiguration;
@@ -340,7 +342,7 @@
basicStream.onShow();
// Advance so that the spinner starts showing
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
// Advance so that is has taken long enough that onOpenedWithNoImmediateContent is logged.
clock.advance(LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS);
@@ -632,7 +634,7 @@
verify(streamDriver, never()).showSpinner();
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
verify(streamDriver).showSpinner();
}
@@ -1004,10 +1006,10 @@
reset(adapter);
// Advance so the spinner is shown.
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
// Advance so that it has shown long enough
- clock.advance(MINIMUM_SPINNER_SHOW_TIME);
+ clock.advance(SPINNER_MINIMUM_SHOW_TIME_MS);
basicStream.onSessionStart(UiContext.getDefaultInstance());
@@ -1020,7 +1022,7 @@
basicStream.onShow();
// Advance so the spinner is shown.
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
reset(adapter);
@@ -1028,7 +1030,7 @@
verify(adapter, never()).setDriver(any(StreamDriver.class));
// Advance so that it has shown long enough.
- clock.advance(MINIMUM_SPINNER_SHOW_TIME);
+ clock.advance(SPINNER_MINIMUM_SHOW_TIME_MS);
verify(adapter).setDriver(streamDriver);
}
@@ -1042,13 +1044,13 @@
reset(adapter);
// Advance so the spinner is shown.
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
basicStream.onSessionStart(UiContext.getDefaultInstance());
basicStream.onSessionFinished(UiContext.getDefaultInstance());
// Advance so that it has shown long enough.
- clock.advance(MINIMUM_SPINNER_SHOW_TIME);
+ clock.advance(SPINNER_MINIMUM_SHOW_TIME_MS);
verify(adapter, never()).setDriver(streamDriver);
}
@@ -1070,7 +1072,20 @@
verify(streamDriver, never()).showSpinner();
// Advance so the spinner is shown.
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
+
+ verify(streamDriver).showSpinner();
+ }
+
+ @Test
+ public void testOnShow_delaysShowingZeroState_configured_delay_time() {
+ basicStream.onShow();
+
+ verify(streamDriver, never()).showZeroState(/* zeroStateShowReason= */ anyInt());
+ verify(streamDriver, never()).showSpinner();
+
+ // Advance so the spinner is shown.
+ clock.advance(SPINNER_DELAY_MS);
verify(streamDriver).showSpinner();
}
@@ -1164,7 +1179,7 @@
basicStream.onSessionFinished(UiContext.getDefaultInstance());
- clock.advance(BasicStream.MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
verify(streamDriver).showSpinner();
}
@@ -1174,7 +1189,7 @@
basicStream.onShow();
// Advance, but not enough so that the spinner shows.
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER / 2);
+ clock.advance(SPINNER_DELAY_MS / 2);
// Start the session. At this point, the spinner enqueued by onShow() should never be shown.
basicStream.onSessionStart(UiContext.getDefaultInstance());
@@ -1185,7 +1200,7 @@
// It has now been long enough since onShow that the spinner would show if onSessionStart()
// hadn't been called first.
- clock.advance(BasicStream.MINIMUM_TIME_BEFORE_SHOWING_SPINNER / 2);
+ clock.advance(SPINNER_DELAY_MS / 2 + 1);
verify(streamDriver, never()).showSpinner();
}
@@ -1199,7 +1214,7 @@
verify(streamDriver, never()).showSpinner();
- clock.advance(MINIMUM_TIME_BEFORE_SHOWING_SPINNER);
+ clock.advance(SPINNER_DELAY_MS);
verify(streamDriver).showSpinner();
}