diff --git a/src/player.jsx b/src/player.jsx
index e0e2fe4..6e5444d 100644
--- a/src/player.jsx
+++ b/src/player.jsx
@@ -26,21 +26,6 @@ let $ = require("jquery");
require("console.css");
require("bootstrap-slider");
-/*
- * Get an object field, verifying its presence and type.
- */
-let getValidField = function (object, field, type) {
- let value;
- if (!(field in object)) {
- throw Error("\"" + field + "\" field is missing");
- }
- value = object[field];
- if (typeof (value) != typeof (type)) {
- throw Error("invalid \"" + field + "\" field type: " + typeof (value));
- }
- return value;
-};
-
let scrollToBottom = function(id) {
const el = document.getElementById(id);
if (el) {
@@ -48,6 +33,54 @@ let scrollToBottom = function(id) {
}
};
+function ErrorList(props) {
+ let list = [];
+
+ if (props.list) {
+ list = props.list.map((message, key) => { return });
+ }
+
+ return (
+
+ {list}
+
+ );
+}
+
+function ErrorItem(props) {
+ return (
+
+
+
+ {props.message}
+
+ );
+}
+
+let ErrorService = class {
+ constructor() {
+ this.addMessage = this.addMessage.bind(this);
+ this.errors = [];
+ }
+
+ addMessage(message) {
+ if (typeof message === "object" && message !== null) {
+ if ("toString" in message) {
+ message = message.toString();
+ } else {
+ message = _("unknown error");
+ }
+ }
+ if (typeof message === "string" || message instanceof String) {
+ if (this.errors.indexOf(message) === -1) {
+ this.errors.push(message);
+ }
+ }
+ }
+};
+
/*
* An auto-loading buffer of recording's packets.
*/
@@ -55,10 +88,11 @@ let PacketBuffer = class {
/*
* Initialize a buffer.
*/
- constructor(matchList) {
+ constructor(matchList, reportError) {
this.handleError = this.handleError.bind(this);
this.handleStream = this.handleStream.bind(this);
this.handleDone = this.handleDone.bind(this);
+ this.getValidField = this.getValidField.bind(this);
/* RegExp used to parse message's timing field */
this.timingRE = new RegExp(
/* Delay (1) */
@@ -81,6 +115,7 @@ let PacketBuffer = class {
);
/* List of matches to apply when loading the buffer from Journal */
this.matchList = matchList;
+ this.reportError = reportError;
/*
* An array of two-element arrays (tuples) each containing a
* packet index and a deferred object. The list is kept sorted to
@@ -119,6 +154,21 @@ let PacketBuffer = class {
this.done = false;
}
+ /*
+ * Get an object field, verifying its presence and type.
+ */
+ getValidField(object, field, type) {
+ let value;
+ if (!(field in object)) {
+ this.reportError("\"" + field + "\" field is missing");
+ }
+ value = object[field];
+ if (typeof (value) != typeof (type)) {
+ this.reportError("invalid \"" + field + "\" field type: " + typeof (value));
+ }
+ return value;
+ }
+
/*
* Return a promise which is resolved when a packet at a particular
* index is received by the buffer. The promise is rejected with a
@@ -235,6 +285,7 @@ let PacketBuffer = class {
this.idxDfdList[i][1].reject(error);
}
this.idxDfdList = [];
+ this.reportError(error);
}
/*
@@ -257,7 +308,7 @@ let PacketBuffer = class {
/* Match next timing entry */
matches = this.timingRE.exec(timing);
if (matches === null) {
- throw Error("invalid timing string");
+ this.reportError(_("invalid timing string"));
} else if (matches[0] == "") {
break;
}
@@ -297,7 +348,7 @@ let PacketBuffer = class {
/* Add (replacement) input characters */
s = in_txt.slice(in_txt_pos, in_txt_pos += x);
if (s.length != x) {
- throw Error("timing entry out of input bounds");
+ this.reportError(_("timing entry out of input bounds"));
}
io.push(s);
break;
@@ -319,7 +370,7 @@ let PacketBuffer = class {
/* Add (replacement) output characters */
s = out_txt.slice(out_txt_pos, out_txt_pos += x);
if (s.length != x) {
- throw Error("timing entry out of output bounds");
+ this.reportError(_("timing entry out of output bounds"));
}
io.push(s);
break;
@@ -348,10 +399,10 @@ let PacketBuffer = class {
}
if (in_txt_pos < in_txt.length) {
- throw Error("extra input present");
+ this.reportError(_("extra input present"));
}
if (out_txt_pos < out_txt.length) {
- throw Error("extra output present");
+ this.reportError(_("extra output present"));
}
if (io.length > 0) {
@@ -375,24 +426,24 @@ let PacketBuffer = class {
const string = String();
/* Check version */
- ver = getValidField(message, "ver", string);
+ ver = this.getValidField(message, "ver", string);
matches = ver.match("^(\\d+)\\.(\\d+)$");
if (matches === null || matches[1] > 2) {
- throw Error("\"ver\" field has invalid value: " + ver);
+ this.reportError("\"ver\" field has invalid value: " + ver);
}
/* TODO Perhaps check host, rec, user, term, and session fields */
/* Extract message ID */
- id = getValidField(message, "id", number);
+ id = this.getValidField(message, "id", number);
if (id <= this.id) {
- throw Error("out of order \"id\" field value: " + id);
+ this.reportError("out of order \"id\" field value: " + id);
}
/* Extract message time position */
- pos = getValidField(message, "pos", number);
+ pos = this.getValidField(message, "pos", number);
if (pos < this.message_pos) {
- throw Error("out of order \"pos\" field value: " + pos);
+ this.reportError("out of order \"pos\" field value: " + pos);
}
/* Update last received message ID and time position */
@@ -401,9 +452,9 @@ let PacketBuffer = class {
/* Parse message data */
this.parseMessageData(
- getValidField(message, "timing", string),
- getValidField(message, "in_txt", string),
- getValidField(message, "out_txt", string));
+ this.getValidField(message, "timing", string),
+ this.getValidField(message, "in_txt", string),
+ this.getValidField(message, "out_txt", string));
}
/*
@@ -573,7 +624,6 @@ export class Player extends React.Component {
containerWidth: 630,
currentTsPost: 0,
scale: 1,
- error: null,
input: "",
mark: 0,
};
@@ -581,7 +631,9 @@ export class Player extends React.Component {
this.containerHeight = 290;
/* Auto-loading buffer of recording's packets */
- this.buf = new PacketBuffer(this.props.matchList);
+ this.error_service = new ErrorService();
+ this.reportError = this.error_service.addMessage;
+ this.buf = new PacketBuffer(this.props.matchList, this.reportError);
/* Current recording time, ms */
this.recTS = 0;
@@ -655,7 +707,7 @@ export class Player extends React.Component {
/* Handle packet retrieval error */
handleError(error) {
if (error !== null) {
- this.setState({error: error});
+ this.reportError(error);
console.warn(error);
}
}
@@ -1046,18 +1098,6 @@ export class Player extends React.Component {
"float": "right",
};
- let error = "";
- if (this.state.error) {
- error = (
-
-
-
- {this.state.error}.
-
);
- }
-
// ensure react never reuses this div by keying it with the terminal widget
return (
@@ -1124,8 +1164,8 @@ export class Player extends React.Component {
+
- {error}