diff --git a/modules/static/charybdis.css b/modules/static/charybdis.css
index d4c1db734..70d0bc942 100644
--- a/modules/static/charybdis.css
+++ b/modules/static/charybdis.css
@@ -2614,6 +2614,8 @@ div.main > form.search label
.ircd .room div.members .menu .item
{
+ padding-left: 0px;
+ padding-right: 0px;
}
.ircd .room div.members .menu .item .name
diff --git a/modules/static/charybdis.js b/modules/static/charybdis.js
index 866e0bcdf..59a3c96e3 100644
--- a/modules/static/charybdis.js
+++ b/modules/static/charybdis.js
@@ -71,7 +71,8 @@ mc.ready = async function(event)
catch(error)
{
console.error("IRCd Charybdis Client: Main exited (error): " + error + " " + error.stack);
- mc.unhandled(error);
+ //mc.unhandled(error);
+ mc.abort(error);
}
finally
{
diff --git a/modules/static/charybdis/io.request.js b/modules/static/charybdis/io.request.js
index 96228d4d6..56ed155f6 100644
--- a/modules/static/charybdis/io.request.js
+++ b/modules/static/charybdis/io.request.js
@@ -161,6 +161,8 @@ mc.io.request.constructor = function(ctx = {})
// Insert request into active table. The request can be aborted hereafter.
mc.io.requests.insert(this);
+ this.started = mc.now();
+
// This should be done here for now
this.xhr.open(this.ctx.method, this.ctx.url);
@@ -390,6 +392,7 @@ mc.io.request.on.readystatechange = function(event)
{
let state = this.xhr.readyState;
let handler = mc.io.request.on.readystatechange[state];
+ this.event = event;
// The promise is resolved for the user before the lib's handlers are called.
// This is because the DONE handler has to fulfill all outstanding promises for
@@ -499,40 +502,56 @@ mc.io.request.success = function(event)
mc.io.request.error = function(event)
{
- let xhr = this.xhr;
- let response = xhr.response;
- let error =
+ let error = new mc.error(
{
- name:
- xhr.statusText == "error"? "Network Request Error":
- empty(xhr.statusText)? "abort":
- xhr.statusText,
-
- status:
- xhr.status != 0? xhr.status : "client side",
-
- m:
- xhr.responseType == "json"? xhr.response : undefined,
-
message:
!empty(this.reason)?
this.reason:
- response && xhr.responseType == "text"?
- response:
- "There may be a network connectivity problem.",
+ this.response && this.xhr.responseType == "text"?
+ this.xhr.responseText:
+ this.started + this.ctx.timeout <= mc.now()?
+ "timeout":
+ maybe(() => this.event.detail)?
+ this.event.detail:
+ undefined,
+
+ name:
+ this.xhr.statusText == "error"?
+ "Network Request Error":
+ this.xhr.statusText == "abort"?
+ "Network Request Canceled":
+ !empty(this.xhr.statusText)?
+ this.xhr.statusText:
+ this.started + this.ctx.timeout <= mc.now()?
+ "timeout":
+ !empty(this.reason)?
+ this.reason:
+ !window.navigator.onLine?
+ "disconnected":
+ this.started + 10 > mc.now()?
+ "killed":
+ "timeout",
+
+ status:
+ this.xhr.status != 0? this.xhr.status : "Client",
+
+ m:
+ this.xhr.responseType == "json"? this.xhr.response : undefined,
request_stack:
this.stack,
+ event:
+ this.event,
+
element:
this.ctx.element,
- };
+ });
- if(!empty(error.m))
- delete error.message;
+ //if(!empty(error.m))
+ // delete error.message;
let data = undefined;
- error = new mc.error(error);
mc.io.request.continuation.call(this, error, data);
};
diff --git a/modules/static/charybdis/main.js b/modules/static/charybdis/main.js
index 4483313fc..78c5b0733 100644
--- a/modules/static/charybdis/main.js
+++ b/modules/static/charybdis/main.js
@@ -101,6 +101,15 @@ mc.main.init = async function()
*/
mc.main.fini = async function()
{
+ console.log("Synchronizing WebStorage..."); try
+ {
+ mc.storage.sync();
+ }
+ catch(error)
+ {
+ console.error("Error synchronizing WebStorage: " + error);
+ }
+
console.log("Stopping remaining tasks..."); try
{
await mc.main.interrupt();
@@ -132,7 +141,7 @@ mc.main.fini = async function()
mc.main.on_logout();
}
- console.log("Synchronizing WebStorage..."); try
+ console.log("Resynchronizing WebStorage..."); try
{
mc.storage.sync();
}
@@ -140,6 +149,15 @@ mc.main.fini = async function()
{
console.error("Error synchronizing WebStorage: " + error);
}
+
+ console.log("Final angular repaint..."); try
+ {
+ mc.ng.apply();
+ }
+ catch(error)
+ {
+ console.error("Error repainting: " + error);
+ }
};
/**
@@ -172,13 +190,39 @@ mc.main.fault = async function(error)
switch(error.status)
{
- case "Client Side":
- if(error.name == "abort")
+ case "Client":
+ if(error.name == "disconnected")
+ {
+ console.warn("client disconnected");
+ mc.unhandled(error);
return false;
+ }
+
+ if(error.name == "killed")
+ {
+ console.error("client fatal");
+ mc.unhandled(error);
+ return false;
+ }
+
+ if(error.name == "timeout")
+ {
+ console.warn("client timeout");
+ mc.ng.root().error = undefined;
+ mc.ng.mc().error = undefined;
+ return true;
+ }
+
+ console.warn("client unhandled " + error);
+ mc.unhandled(error);
+ return false;
default:
+ console.error("fault unhandled");
throw error;
}
+
+ return false;
};
/**
diff --git a/modules/static/charybdis/sync.js b/modules/static/charybdis/sync.js
index 6b3801aa4..3ce9c814a 100644
--- a/modules/static/charybdis/sync.js
+++ b/modules/static/charybdis/sync.js
@@ -46,18 +46,22 @@ mc.sync = async function(opts = {})
});
let request = mc.m.sync.get(opts);
- let data = await request.response;
- opts.query.since = maybe(() => data.next_batch);
-
- if(mc.opts.sync_debug)
- debug.object(data, mc.opts.sync_debug);
-
- for(let key in data)
{
- let handler = mc.sync[key];
- if(handler !== undefined)
- handler(data[key]);
+ let data = await request.response;
+ opts.query.since = maybe(() => data.next_batch);
+
+ if(mc.opts.sync_debug)
+ debug.object(data, mc.opts.sync_debug);
+
+ for(let key in data)
+ {
+ let handler = mc.sync[key];
+ if(handler !== undefined)
+ handler(data[key]);
+ }
}
+
+ return true;
};
mc.sync["rooms"] = function(rooms)
diff --git a/modules/static/index.html b/modules/static/index.html
index b8a7d7e59..c571ea726 100644
--- a/modules/static/index.html
+++ b/modules/static/index.html
@@ -2248,6 +2248,42 @@ type="text/ng-template"
+
+