Skip to content

Commit 9521af0

Browse files
authored
Schedule rebuild immediately on scroll to avoid flicker. (#65)
Schedule rebuild immediately on scroll to avoid flicker. Use visibility observers instead of guessing at when visibility changes. Fixes bug when initially only 4 rows were drawn for the memory view.
1 parent 91d5556 commit 9521af0

File tree

3 files changed

+25
-79
lines changed

3 files changed

+25
-79
lines changed

lib/framework/framework.dart

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,22 @@ class Framework {
3636
assert(screen != null);
3737

3838
final String search = window.location.search;
39-
final String ref = search == null ? screen.ref : '${screen.ref}$search';
39+
final String ref = search == null ? screen.ref : '$search${screen.ref}';
4040
window.history.pushState(null, screen.name, ref);
4141

4242
load(screen);
4343
}
4444

4545
void loadScreenFromLocation() {
46-
// Look for an explicit path, otherwise re-direct to '/'
47-
String path = window.location.pathname;
48-
49-
// Special case the development path.
50-
if (path == '/devtools/web/index.html' || path == '/index.html') {
51-
path = '/';
52-
}
53-
54-
final String first =
55-
(path.startsWith('/') ? path.substring(1) : path).split('/').first;
56-
Screen screen = getScreen(first.isEmpty ? path : first);
57-
if (screen == null && path == '/') {
58-
screen = screens.first;
46+
// Screens are identified by the hash as that works better with the webdev
47+
// server.
48+
String id = window.location.hash;
49+
if (id.isNotEmpty) {
50+
assert(id[0] == '#');
51+
id = id.substring(1);
5952
}
53+
Screen screen = getScreen(id);
54+
screen ??= screens.first;
6055
if (screen != null) {
6156
load(screen);
6257
} else {
@@ -218,7 +213,7 @@ abstract class Screen {
218213

219214
final List<StatusItem> statusItems = <StatusItem>[];
220215

221-
String get ref => id == '/' ? id : '/$id';
216+
String get ref => id.isEmpty ? id : '#$id';
222217

223218
bool get visible => _visible.value;
224219

lib/tables.dart

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:async';
66
import 'dart:html';
7+
import 'dart:js';
78

89
import 'package:devtools/framework/framework.dart';
910
import 'package:meta/meta.dart';
@@ -13,7 +14,7 @@ import 'utils.dart';
1314

1415
// TODO(devoncarew): fixed position header
1516

16-
class Table<T> extends Object with SetStateMixin, OnAddedToDomMixin {
17+
class Table<T> extends Object with SetStateMixin {
1718
Table()
1819
: element = div(a: 'flex', c: 'overflow-y table-border'),
1920
_isVirtual = false,
@@ -28,10 +29,16 @@ class Table<T> extends Object with SetStateMixin, OnAddedToDomMixin {
2829
_spacerBeforeVisibleRows = new CoreElement('tr');
2930
_spacerAfterVisibleRows = new CoreElement('tr');
3031

31-
element.onScroll.listen((_) => _scheduleRebuild());
32+
// TODO(jacobr): remove call to allowInterop once
33+
// https://github.com/dart-lang/sdk/issues/35484 is fixed.
34+
_visibilityObserver = new IntersectionObserver(allowInterop(_visibilityChange));
35+
_visibilityObserver.observe(_spacerBeforeVisibleRows.element);
36+
_visibilityObserver.observe(_spacerAfterVisibleRows.element);
37+
element.onScroll.listen((_) => _rebuildTable());
3238
}
3339

34-
@override
40+
IntersectionObserver _visibilityObserver;
41+
3542
final CoreElement element;
3643
final bool _isVirtual;
3744

@@ -69,9 +76,6 @@ class Table<T> extends Object with SetStateMixin, OnAddedToDomMixin {
6976
new StreamController<T>.broadcast();
7077

7178
void _init() {
72-
_monitorWindowResizes();
73-
_rebuildWhenAddedToDom();
74-
7579
element.add(_table);
7680
_table.onKeyDown.listen((KeyboardEvent e) {
7781
int indexOffset;
@@ -98,29 +102,8 @@ class Table<T> extends Object with SetStateMixin, OnAddedToDomMixin {
98102
});
99103
}
100104

101-
StreamSubscription<Event> _windowResizeSubscription;
102-
void _monitorWindowResizes() {
103-
// Monitor Window resizes but don't rebuild if we're not in the DOM.
104-
_windowResizeSubscription = window.onResize.listen((_) {
105-
if (!isInDom) {
106-
return;
107-
}
108-
_scheduleRebuild();
109-
});
110-
}
111-
112-
StreamSubscription<void> _addToDomSubscription;
113-
void _rebuildWhenAddedToDom() {
114-
// When we're added to the DOM, force a rebuild since we may have
115-
// resized the window while we were not in the DOM.
116-
_addToDomSubscription = onAddedToDom.listen((_) => _scheduleRebuild());
117-
}
118-
119105
void dispose() {
120-
_windowResizeSubscription?.cancel();
121-
_windowResizeSubscription = null;
122-
_addToDomSubscription?.cancel();
123-
_addToDomSubscription = null;
106+
_visibilityObserver.disconnect();
124107
}
125108

126109
Stream<T> get onSelect => _selectController.stream;
@@ -506,6 +489,10 @@ class Table<T> extends Object with SetStateMixin, OnAddedToDomMixin {
506489
_doSort();
507490
_scheduleRebuild();
508491
}
492+
493+
void _visibilityChange(List entries, IntersectionObserver observer) {
494+
_scheduleRebuild();
495+
}
509496
}
510497

511498
abstract class Column<T> {

lib/ui/elements.dart

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -310,39 +310,3 @@ class TrustedHtmlTreeSanitizer implements NodeTreeSanitizer {
310310
@override
311311
void sanitizeTree(Node node) {}
312312
}
313-
314-
abstract class CoreElementOwner {
315-
CoreElement get element;
316-
}
317-
318-
// TODO(dantup): Remove this (plus HasCoreElement above) when we methods on
319-
// CoreElement to handle add/remove from DOM.
320-
abstract class OnAddedToDomMixin implements CoreElementOwner {
321-
bool isInDom = false;
322-
MutationObserver observer;
323-
final StreamController<void> _addedToDomController =
324-
new StreamController<void>.broadcast();
325-
326-
Stream<void> get onAddedToDom {
327-
// Set up an observer that can detect when this element is added to the DOM.
328-
// TODO(dantup): Can mixins have anything like constructors?
329-
if (observer == null) {
330-
observer = new MutationObserver(
331-
(List<dynamic> mutations, MutationObserver observer) {
332-
if (document.body.contains(element.element) && !isInDom) {
333-
isInDom = true;
334-
_addedToDomController.add(null);
335-
} else if (!document.body.contains(element.element) && isInDom) {
336-
isInDom = false;
337-
}
338-
});
339-
340-
// Enable/disable the observer based on whether anyone is listening.
341-
_addedToDomController.onListen =
342-
() => observer.observe(document.body, childList: true, subtree: true);
343-
_addedToDomController.onCancel = () => observer.disconnect();
344-
}
345-
346-
return _addedToDomController.stream;
347-
}
348-
}

0 commit comments

Comments
 (0)