diff --git a/MirrorSharp.WebAssets/wwwroot/css/mirrorsharp.css b/MirrorSharp.WebAssets/wwwroot/css/mirrorsharp.css
index 7e309fe1..79c9f107 100644
--- a/MirrorSharp.WebAssets/wwwroot/css/mirrorsharp.css
+++ b/MirrorSharp.WebAssets/wwwroot/css/mirrorsharp.css
@@ -6,6 +6,47 @@
font-size: inherit;
}
+/*.mirrorsharp-status {
+ position: absolute;
+ width: 0.7em;
+ height: 0.7em;
+ right: 0.35em;
+ top: 0.35em;
+ transform: rotate(45deg);
+ opacity: 0.7;
+}
+
+.mirrorsharp-status-connected {
+ background-color: #2ecc71;
+}*/
+
+.mirrorsharp-connection-issue {
+ display: none;
+ position: absolute;
+ top: 0;
+ background: #aaa;
+ right: 0;
+ left: 0;
+ color: #fff;
+ padding: 0.2em 0.4em;
+}
+
+.mirrorsharp-connection-has-issue .mirrorsharp-connection-issue {
+ display: block;
+}
+
+.CodeMirror.mirrorsharp-connection-has-issue {
+ padding-top: 1.6em;
+}
+
+.CodeMirror.mirrorsharp-connection-has-issue .CodeMirror-code {
+ color: #aaa;
+}
+
+.CodeMirror.mirrorsharp-connection-has-issue .CodeMirror-code * {
+ color: inherit;
+}
+
.mirrorsharp-hint {
display: flex;
padding-left: 0;
diff --git a/MirrorSharp.WebAssets/wwwroot/js/mirrorsharp.js b/MirrorSharp.WebAssets/wwwroot/js/mirrorsharp.js
index 3f62a713..c7786937 100644
--- a/MirrorSharp.WebAssets/wwwroot/js/mirrorsharp.js
+++ b/MirrorSharp.WebAssets/wwwroot/js/mirrorsharp.js
@@ -1,4 +1,5 @@
-(function (root, factory) {
+/* globals define:false */
+(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['CodeMirror'], factory);
} else if (typeof module === 'object' && module.exports) {
@@ -7,14 +8,46 @@
root.mirrorsharp = factory(root.CodeMirror);
}
}(this, function (CodeMirror) {
- function Connection(socket) {
- const openPromise = new Promise(function(resolve) {
- socket.addEventListener('open', function (e) {
- //console.debug("[open]");
- resolve();
- });
+ 'use strict';
+
+ function Connection(openSocket) {
+ var socket;
+ var openPromise;
+ const handlers = {
+ open: [],
+ message: [],
+ close: []
+ };
+
+ open();
+ on('close', function() {
+ setTimeout(function() { open(); }, 1000);
});
+ function open() {
+ socket = openSocket();
+ openPromise = new Promise(function (resolve) {
+ socket.addEventListener('open', function() {
+ resolve();
+ });
+ });
+
+ for (var key in handlers) {
+ const keyFixed = key;
+ const handlersByKey = handlers[key];
+ socket.addEventListener(key, function (e) {
+ var argument = (keyFixed === 'message') ? JSON.parse(e.data) : undefined;
+ for (var handler of handlersByKey) {
+ handler(argument);
+ }
+ });
+ }
+ }
+
+ function on(key, handler) {
+ handlers[key].push(handler);
+ }
+
function sendWhenOpen(command) {
openPromise.then(function () {
//console.debug("[=>]", command);
@@ -22,6 +55,8 @@
});
}
+ this.on = on;
+
this.sendReplaceText = function (isLastOrOnly, start, length, newText, cursorIndexAfter) {
const command = isLastOrOnly ? 'R' : 'P';
return sendWhenOpen(command + start + ':' + length + ':' + cursorIndexAfter + ':' + newText);
@@ -42,14 +77,6 @@
this.sendGetDiagnostics = function () {
return sendWhenOpen('D');
}
-
- this.onMessage = function(handler) {
- socket.addEventListener('message', function (e) {
- //console.debug("[<=]", e.data);
- const message = JSON.parse(e.data);
- handler(message);
- });
- }
}
function Editor(textarea, connection, options) {
@@ -58,20 +85,39 @@
cmOptions.gutters.push('CodeMirror-lint-markers');
const cm = CodeMirror.fromTextArea(textarea, cmOptions);
- var initialTextSent = false;
+ /*(function createStatusElement() {
+ const cmWrapper = cm.getWrapperElement();
+ const element = document.createElement('div');
+ element.className = 'mirrorsharp-status';
+ cmWrapper.appendChild(element);
+ connection.onOpen(function () {
+ element.classList.add('mirrorsharp-status-connected');
+ });
+
+ return element;
+ })();*/
+
+ var lintingSuspended = true;
var updateLinting;
- (function sendOnStart() {
+ connection.on('open', function () {
+ hideConnectionLoss();
+
const text = cm.getValue();
if (text === '' || text == null) {
- initialTextSent = true;
+ lintingSuspended = false;
return;
}
- connection.sendReplaceText(true, 0, 0, text, 0);
- initialTextSent = true;
+ connection.sendReplaceText(true, 0, 0, text, getCursorIndex(cm));
+ lintingSuspended = false;
if (updateLinting)
requestDiagnostics(text, updateLinting);
- })();
+ });
+
+ connection.on('close', function () {
+ lintingSuspended = true;
+ showConnectionLoss();
+ });
const indexKey = '$mirrorsharp-index';
var changePending = false;
@@ -106,7 +152,7 @@
}
});
- connection.onMessage(function (message) {
+ connection.on('message', function (message) {
switch (message.type) {
case 'changes':
applyChangesFromServer(message.changes);
@@ -174,7 +220,7 @@
function requestDiagnostics(text, updateLintingValue) {
updateLinting = updateLintingValue;
- if (initialTextSent)
+ if (!lintingSuspended)
connection.sendGetDiagnostics();
}
@@ -201,10 +247,30 @@
if (clientCursorIndex !== serverCursorIndex)
console.error('Client cursor position does not match server position:', { clientPosition: clientCursorIndex, serverPosition: serverCursorIndex });
}
+
+ var connectionLossElement;
+ function showConnectionLoss() {
+ const wrapper = cm.getWrapperElement();
+ if (!connectionLossElement) {
+ connectionLossElement = document.createElement("div");
+ connectionLossElement.setAttribute('class', 'mirrorsharp-connection-issue');
+ connectionLossElement.innerText = 'Server connection lost, reconnecting…';
+ wrapper.appendChild(connectionLossElement);
+ }
+
+ wrapper.classList.add('mirrorsharp-connection-has-issue');
+ }
+
+ function hideConnectionLoss() {
+ cm.getWrapperElement().classList.remove('mirrorsharp-connection-has-issue');
+ }
}
return function(textarea, options) {
- const connection = new Connection(new WebSocket(options.serviceUrl));
+ const connection = new Connection(function() {
+ return new WebSocket(options.serviceUrl);
+ });
+
return new Editor(textarea, connection, options);
}
}));
\ No newline at end of file
diff --git a/MirrorSharp.sln.DotSettings b/MirrorSharp.sln.DotSettings
index e13f67bc..bc74da31 100644
--- a/MirrorSharp.sln.DotSettings
+++ b/MirrorSharp.sln.DotSettings
@@ -2,6 +2,8 @@
C27+,E12+,FF21+,IE11+,S8+
ExplicitlyExcluded
ExplicitlyExcluded
+ HINT
+ HINT
END_OF_LINE
END_OF_LINE
END_OF_LINE
@@ -11,6 +13,8 @@
END_OF_LINE
False
END_OF_LINE
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy>
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />