Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Unified Diff: web/inc/logdog-stream-view/view.ts

Issue 2988993003: [logdog-view] Update UX, fix bugs. (Closed)
Patch Set: unfollow only on up scroll Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « web/inc/logdog-stream-view/model.ts ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: web/inc/logdog-stream-view/view.ts
diff --git a/web/inc/logdog-stream-view/view.ts b/web/inc/logdog-stream-view/view.ts
index 7ebe3d9ca90bf866e630deeac218f0e4b30eda38..400bb2acc6427578c9aac04eee3b89b1f8bdd81a 100644
--- a/web/inc/logdog-stream-view/view.ts
+++ b/web/inc/logdog-stream-view/view.ts
@@ -28,6 +28,8 @@ namespace LogDog {
LOADING_BEEN_A_WHILE,
/** Rendering loaded stream content. */
RENDERING,
+ /** No operations in progress, but the log isn't fully loaded.. */
+ PAUSED,
/** Error: Attempt to load failed w/ "Unauthenticated". */
NEEDS_AUTH,
/** Error: generic loading failure. */
@@ -43,16 +45,26 @@ namespace LogDog {
locationIsVisible(l: Location): boolean;
}
- /** Represents control visibility in the View. */
+ /** State of the split UI component. */
+ export enum SplitState {
+ /** The UI cannot be split. */
+ CANNOT_SPLIT,
+ /** The UI can be split, and isn't split. */
+ CAN_SPLIT,
+ /** The UI cannot be split, and is split. */
+ IS_SPLIT,
+ }
+
+ /**
+ * Represents state in the View.
+ *
+ * Modifying this will propagate to the view via "updateControls".
+ */
type Controls = {
- /** Are we completely finished loading stream data? */
- canSplit: boolean;
- /** Are we currently split? */
- split: boolean;
- /** Show the bottom bar? */
- bottom: boolean;
/** Is the content fully loaded? */
fullyLoaded: boolean;
+ /** True if we should show the split option to the user. */
+ splitState: SplitState;
/** If not undefined, link to this URL for the log stream. */
logStreamUrl: string | undefined;
@@ -88,12 +100,17 @@ namespace LogDog {
mobile: boolean;
isSplit: boolean;
metadata: boolean;
- follow: boolean;
playing: boolean;
backfill: boolean;
/** Polymer read-only setter functions. */
_setStatusBar(v: StatusBarValue|null): void;
+
+ _setShowPlayPause(v: boolean): void;
+ _setShowStreamControls(v: boolean): void;
+ _setShowSplitButton(v: boolean): void;
+ _setShowSplitControls(v: boolean): void;
+
_setCanSplit(v: boolean): void;
_setIsSplit(v: boolean): void;
_setShowStreamingControls(v: boolean): void;
@@ -127,6 +144,13 @@ namespace LogDog {
private model: Model|null = null;
private renderedLogs = false;
+ /**
+ * We start out following by default. Every time we add new logs to the
+ * bottom, we will scroll to them. If users scroll or pause, we will stop
+ * following permanently.
+ */
+ private following = true;
+
constructor(readonly comp: Component) {}
/** Resets and reloads current viewer state. */
@@ -156,8 +180,11 @@ namespace LogDog {
}
/** Called when a mouse wheel event occurs. */
- handleMouseWheel() {
- this.comp.follow = false;
+ handleMouseWheel(down: boolean) {
+ // Once someone scrolls, stop following.
+ if (!down) {
+ this.following = false;
+ }
}
/** Called when the split "Down" button is clicked. */
@@ -194,17 +221,36 @@ namespace LogDog {
// Perform the initial fetch after resolution.
if (this.model) {
- this.model.setAutomatic(this.comp.playing);
+ this.model.automatic = this.comp.playing;
this.model.setFetchFromTail(!this.comp.backfill);
this.model.fetch(false);
}
}
+ stop() {
+ if (this.model) {
+ this.model.automatic = false;
+ this.model.clearCurrentOperation();
+ }
+ }
+
/** Called when the "playing" property value changes. */
- handlePlayingChanged(v: boolean) {
+ handlePlayPauseChanged(v: boolean) {
if (this.model) {
// If we're playing, begin log fetching.
- this.model.setAutomatic(v);
+ this.model.automatic = v;
+
+ // Once someone manually uses this control, stop following.
+ //
+ // Only apply this after we've started rendering logs, since before that
+ // this may toggle during setup.
+ if (this.renderedLogs) {
+ this.following = false;
+ }
+
+ if (!v) {
+ this.model.clearCurrentOperation();
+ }
}
}
@@ -216,17 +262,6 @@ namespace LogDog {
}
}
- /** Called when the "follow" property value changes. */
- handleFollowChanged(v: boolean) {
- if (this.model) {
- if (v) {
- // If follow is toggled on, automatically begin playing.
- this.comp.playing = true;
- this.maybeScrollToFollow();
- }
- }
- }
-
/** Called when the "split" button is clicked. */
handleSplitClicked() {
if (!this.model) {
@@ -234,14 +269,14 @@ namespace LogDog {
}
// After a split, toggle off playing.
- this.model.split();
this.model.setFetchFromTail(true);
+ this.model.split();
this.comp.playing = false;
}
/** Called when the "scroll to split" button is clicked. */
handleScrollToSplitClicked() {
- this.maybeScrollToElement(this.comp.$.logSplit, true, true);
+ this.maybeScrollToElement(this.comp.$.logSplit, true);
}
/** Called when a sign-in event is fired from "google-signin-aware". */
@@ -251,6 +286,11 @@ namespace LogDog {
}
}
+ /** Returns true if our Model is currently automatically loading logs. */
+ private get isPlaying() {
+ return (this.model && this.model.automatic);
+ }
+
/** Clears asynchornous scroll event status. */
private resetScroll() {
if (this.scrollTimeoutId !== null) {
@@ -387,7 +427,6 @@ namespace LogDog {
// Add the log entry to the appropriate place.
let anchor: Element|null;
let scrollToTop = false;
- let forceScroll = false;
switch (insertion) {
case Location.HEAD:
// PREPEND to "logSplit".
@@ -396,6 +435,9 @@ namespace LogDog {
// If we're not split, scroll to the log bottom. Otherwise, scroll to
// the split.
anchor = lastLogEntry;
+ if (this.following) {
+ this.maybeScrollToElement(anchor, scrollToTop);
+ }
break;
case Location.TAIL:
@@ -418,23 +460,21 @@ namespace LogDog {
// When tailing, always scroll to the anchor point.
scrollToTop = true;
- forceScroll = true;
break;
case Location.BOTTOM:
// PREPEND to "logBottom".
anchor = this.comp.$.logBottom;
this.comp.$.logs.insertBefore(logEntryChunk, anchor);
+ if (this.following) {
+ this.maybeScrollToElement(anchor, scrollToTop);
+ }
break;
default:
anchor = null;
break;
}
-
- if (anchor) {
- this.maybeScrollToElement(anchor, scrollToTop, forceScroll);
- }
}
clearLogEntries() {
@@ -466,18 +506,30 @@ namespace LogDog {
return this.elementInViewport(anchor);
}
-
updateControls(c: Controls) {
- this.comp._setCanSplit(c.canSplit);
- this.comp._setIsSplit(c.split);
- this.comp._updateSplitVisible(c.split && this.renderedLogs);
- this.comp._updateBottomVisible(c.bottom && this.renderedLogs);
- this.comp.streamLinkUrl = c.logStreamUrl;
-
- this.comp._setShowStreamingControls(this.renderedLogs && !c.fullyLoaded);
- if (c.fullyLoaded) {
- this.comp.playing = false;
+ let canSplit = false;
+ let isSplit = false;
+ if (!c.fullyLoaded) {
+ switch (c.splitState) {
+ case SplitState.CAN_SPLIT:
+ canSplit = true;
+ break;
+
+ case SplitState.IS_SPLIT:
+ isSplit = true;
+ break;
+
+ default:
+ break;
+ }
}
+ this.comp._setShowPlayPause(!c.fullyLoaded);
+ this.comp._setShowStreamControls(c.fullyLoaded || !this.isPlaying);
+ this.comp._setShowSplitButton(canSplit && !this.isPlaying);
+ this.comp._setShowSplitControls(isSplit);
+ this.comp._updateSplitVisible(isSplit);
+
+ this.comp.streamLinkUrl = c.logStreamUrl;
switch (c.loadingState) {
case LogDog.LoadingState.RESOLVING:
@@ -492,6 +544,9 @@ namespace LogDog {
case LogDog.LoadingState.RENDERING:
this.loadStatusBar('Rendering logs.');
break;
+ case LogDog.LoadingState.PAUSED:
+ this.loadStatusBar('Paused.');
+ break;
case LogDog.LoadingState.NEEDS_AUTH:
this.loadStatusBar('Not authenticated. Please log in.');
break;
@@ -508,38 +563,20 @@ namespace LogDog {
this.comp._setStreamStatus(c.streamStatus);
}
- /** Scrolls to the follow anchor point. */
- private maybeScrollToFollow() {
- // Determine our anchor element.
- let e: HTMLElement;
- if (this.comp.isSplit && this.comp.backfill) {
- // Centering on the split element, at the bottom of the page.
- e = this.comp.$.logSplit;
- } else {
- // Scroll to the bottom of the page.
- e = this.comp.$.logEnd;
- }
-
- this.maybeScrollToElement(e, false, false);
- }
-
/**
* Scrolls to the specified element, centering it at the top or bottom of
* the view. By default,t his will only happen if "follow" is enabled;
* however, it can be forced via "force".
*/
- private maybeScrollToElement(
- element: Element, topOfView: boolean, force: boolean) {
- if (this.comp.follow || force) {
- if (topOfView) {
- element.scrollIntoView({
- behavior: 'auto',
- block: 'end',
- });
- } else {
- // Bug? "block: start" doesn't seem to work the same as false.
- element.scrollIntoView(false);
- }
+ private maybeScrollToElement(element: Element, topOfView: boolean) {
+ if (topOfView) {
+ element.scrollIntoView({
+ behavior: 'auto',
+ block: 'end',
+ });
+ } else {
+ // Bug? "block: start" doesn't seem to work the same as false.
+ element.scrollIntoView(false);
}
}
« no previous file with comments | « web/inc/logdog-stream-view/model.ts ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698