| Index: runtime/observatory/lib/src/elements/vm_connect.dart
|
| diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart
|
| index 37cc2a2a34cb594e067bb4cd9daa8688b4955fd8..e197d54d5384571f77396752a1b435734f274051 100644
|
| --- a/runtime/observatory/lib/src/elements/vm_connect.dart
|
| +++ b/runtime/observatory/lib/src/elements/vm_connect.dart
|
| @@ -4,61 +4,168 @@
|
|
|
| library vm_connect_element;
|
|
|
| -import 'dart:convert';
|
| import 'dart:html';
|
| +import 'dart:async';
|
| +import 'dart:convert';
|
| +import 'package:observatory/models.dart' as M;
|
| +import 'package:observatory/src/elements/helpers/tag.dart';
|
| +import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
|
| +import 'package:observatory/src/elements/nav/bar.dart';
|
| +import 'package:observatory/src/elements/nav/notify.dart';
|
| +import 'package:observatory/src/elements/nav/top_menu.dart';
|
| +import 'package:observatory/src/elements/view_footer.dart';
|
| +import 'package:observatory/src/elements/vm_connect_target.dart';
|
|
|
| -import 'observatory_element.dart';
|
| -import 'package:observatory/elements.dart';
|
| -import 'package:observatory/service_html.dart';
|
| -import 'package:polymer/polymer.dart';
|
| +class VMConnectElement extends HtmlElement implements Renderable{
|
| + static const tag = const Tag<VMConnectElement>('vm-connect',
|
| + dependencies: const [NavBarElement.tag,
|
| + NavTopMenuElement.tag,
|
| + NavNotifyElement.tag,
|
| + ViewFooterElement.tag,
|
| + VMConnectTargetElement.tag]);
|
|
|
| -@CustomTag('vm-connect')
|
| -class VMConnectElement extends ObservatoryElement {
|
| - @published String standaloneVmAddress = '';
|
| + RenderingScheduler _r;
|
|
|
| - VMConnectElement.created() : super.created() {
|
| - }
|
| + Stream<RenderedEvent<VMConnectElement>> get onRendered => _r.onRendered;
|
|
|
| - void _connect(WebSocketVMTarget target) {
|
| - app.vm = new WebSocketVM(target);
|
| - app.locationManager.goForwardingParameters('/vm');
|
| + M.DumpRepository _dump;
|
| + M.NotificationRepository _notifications;
|
| + M.TargetRepository _targets;
|
| + StreamSubscription _targetsSubscription;
|
| +
|
| + String _address = '';
|
| +
|
| + factory VMConnectElement(M.TargetRepository targets,
|
| + M.DumpRepository dump,
|
| + M.NotificationRepository notifications,
|
| + {RenderingQueue queue}) {
|
| + assert(dump != null);
|
| + assert(notifications != null);
|
| + assert(targets != null);
|
| + VMConnectElement e = document.createElement(tag.name);
|
| + e._r = new RenderingScheduler(e, queue: queue);
|
| + e._dump = dump;
|
| + e._notifications = notifications;
|
| + e._targets = targets;
|
| + return e;
|
| }
|
|
|
| + VMConnectElement.created() : super.created();
|
| +
|
| @override
|
| void attached() {
|
| - super.attached();
|
| - var fileInput = shadowRoot.querySelector('#crashDumpFile');
|
| - fileInput.onChange.listen(_onCrashDumpFileChange);
|
| + super.attached(); _r.enable();
|
| + _targetsSubscription = _targets.onChange.listen((_) => _r.dirty());
|
| }
|
|
|
| - String _normalizeStandaloneAddress(String networkAddress) {
|
| - if (networkAddress.startsWith('ws://')) {
|
| - return networkAddress;
|
| - }
|
| - return 'ws://${networkAddress}/ws';
|
| + @override
|
| + void detached() {
|
| + super.detached(); children = []; _r.disable(notify: true);
|
| + _targetsSubscription.cancel(); _targetsSubscription = null;
|
| }
|
|
|
| - void connectStandalone(Event e, var detail, Node target) {
|
| - // Prevent any form action.
|
| - e.preventDefault();
|
| - if (standaloneVmAddress == null) {
|
| - return;
|
| - }
|
| - if (standaloneVmAddress.isEmpty) {
|
| - return;
|
| - }
|
| - var targetAddress = _normalizeStandaloneAddress(standaloneVmAddress);
|
| - var target = app.targets.findOrMake(targetAddress);
|
| - _connect(target);
|
| + void render() {
|
| + children = [
|
| + new NavBarElement(queue: _r.queue)
|
| + ..children = [
|
| + new NavTopMenuElement(last: true, queue: _r.queue),
|
| + new NavNotifyElement(_notifications, queue: _r.queue)
|
| + ],
|
| + new DivElement()
|
| + ..classes = ['content-centered']
|
| + ..children = [
|
| + new HeadingElement.h1()..text = 'Connect to a Dart VM',
|
| + new BRElement(), new HRElement(),
|
| + new DivElement()
|
| + ..classes = ['flex-row']
|
| + ..children = [
|
| + new DivElement()
|
| + ..classes = ['flex-item-40-percent']
|
| + ..children = [
|
| + new HeadingElement.h2()..text = 'WebSocket',
|
| + new BRElement(),
|
| + new UListElement()
|
| + ..children = _targets.list().map((target) {
|
| + return new LIElement()
|
| + ..children = [new VMConnectTargetElement(target,
|
| + current: target == _targets.current, queue: _r.queue)
|
| + ..onConnect.listen(_connect)
|
| + ..onDelete.listen(_delete)
|
| + ];
|
| + }),
|
| + new HRElement(),
|
| + new FormElement()
|
| + ..autocomplete = 'on'
|
| + ..children = [
|
| + _createAddressBox(),
|
| + new SpanElement()..text = ' ',
|
| + new ButtonElement()
|
| + ..text = 'Connect'
|
| + ..onClick.listen((e) {
|
| + e.preventDefault(); _create(); }),
|
| + ],
|
| + new BRElement(),
|
| + new PreElement()
|
| + ..classes = ['well']
|
| + ..text = 'Run Standalone with: \'--observe\'',
|
| + new HRElement()
|
| + ],
|
| + new DivElement()
|
| + ..classes = ['flex-item-20-percent'],
|
| + new DivElement()
|
| + ..classes = ['flex-item-40-percent']
|
| + ..children = [
|
| + new HeadingElement.h2()..text = 'Crash dump',
|
| + new BRElement(),
|
| + _createCrushDumpLoader(),
|
| + new BRElement(), new BRElement(),
|
| + new PreElement()
|
| + ..classes = ['well']
|
| + ..text = 'Request a crash dump with:\n'
|
| + '\'curl localhost:8181/_getCrashDump > dump.json\'',
|
| + new HRElement()
|
| + ]
|
| + ],
|
| + ],
|
| + new ViewFooterElement(queue: _r.queue)
|
| + ];
|
| + }
|
| +
|
| + TextInputElement _createAddressBox() {
|
| + var textbox = new TextInputElement()
|
| + ..classes = ['textbox']
|
| + ..placeholder = 'localhost:8181'
|
| + ..value = _address;
|
| + textbox.onChange.listen((e) {
|
| + _address = textbox.value;
|
| + });
|
| + return textbox;
|
| }
|
|
|
| - _onCrashDumpFileChange(e) {
|
| - var fileInput = shadowRoot.querySelector('#crashDumpFile');
|
| - var reader = new FileReader();
|
| - reader.readAsText(fileInput.files[0]);
|
| - reader.onLoad.listen((_) {
|
| - var crashDump = JSON.decode(reader.result);
|
| - app.loadCrashDump(crashDump);
|
| + FileUploadInputElement _createCrushDumpLoader() {
|
| + FileUploadInputElement e = new FileUploadInputElement()
|
| + ..id = 'crashDumpFile';
|
| + e.onChange.listen((_) {
|
| + var reader = new FileReader();
|
| + reader.readAsText(e.files[0]);
|
| + reader.onLoad.listen((_) {
|
| + var crashDump = JSON.decode(reader.result);
|
| + _dump.load(crashDump);
|
| + });
|
| });
|
| + return e;
|
| + }
|
| + void _create() {
|
| + if (_address == null || _address.isEmpty) return;
|
| + _targets.add(_normalizeStandaloneAddress(_address));
|
| + }
|
| + void _connect(TargetEvent e) => _targets.setCurrent(e.target);
|
| + void _delete(TargetEvent e) => _targets.delete(e.target);
|
| +
|
| + static String _normalizeStandaloneAddress(String networkAddress) {
|
| + if (networkAddress.startsWith('ws://')) {
|
| + return networkAddress;
|
| + }
|
| + return 'ws://${networkAddress}/ws';
|
| }
|
| }
|
|
|