ソースを参照

Nicer rendering of MUC disconnection messages

JC Brand 7 年 前
コミット
1880b3f209

+ 41 - 240
css/converse.css

@@ -2371,7 +2371,7 @@
   -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
   -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
 @-ms-viewport {
 @-ms-viewport {
   width: device-width; }
   width: device-width; }
-#conversejs article, #conversejs aside, #conversejs figcaption, #conversejs figure, #conversejs footer, #conversejs header, #conversejs hgroup, #conversejs main, #conversejs nav, #conversejs section {
+#conversejs article, #conversejs aside, #conversejs dialog, #conversejs figcaption, #conversejs figure, #conversejs footer, #conversejs header, #conversejs hgroup, #conversejs main, #conversejs nav, #conversejs section {
   display: block; }
   display: block; }
 #conversejs body {
 #conversejs body {
   margin: 0;
   margin: 0;
@@ -2458,7 +2458,7 @@
 #conversejs code,
 #conversejs code,
 #conversejs kbd,
 #conversejs kbd,
 #conversejs samp {
 #conversejs samp {
-  font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+  font-family: monospace, monospace;
   font-size: 1em; }
   font-size: 1em; }
 #conversejs pre {
 #conversejs pre {
   margin-top: 0;
   margin-top: 0;
@@ -2484,7 +2484,7 @@
   text-align: inherit; }
   text-align: inherit; }
 #conversejs label {
 #conversejs label {
   display: inline-block;
   display: inline-block;
-  margin-bottom: 0.5rem; }
+  margin-bottom: .5rem; }
 #conversejs button {
 #conversejs button {
   border-radius: 0; }
   border-radius: 0; }
 #conversejs button:focus {
 #conversejs button:focus {
@@ -3208,9 +3208,6 @@
   border: 1px solid #ced4da;
   border: 1px solid #ced4da;
   border-radius: 0.25rem;
   border-radius: 0.25rem;
   transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }
   transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }
-  @media screen and (prefers-reduced-motion: reduce) {
-    #conversejs .form-control {
-      transition: none; } }
   #conversejs .form-control::-ms-expand {
   #conversejs .form-control::-ms-expand {
     background-color: transparent;
     background-color: transparent;
     border: 0; }
     border: 0; }
@@ -3258,7 +3255,6 @@
   padding-bottom: 0.375rem;
   padding-bottom: 0.375rem;
   margin-bottom: 0;
   margin-bottom: 0;
   line-height: 1.5;
   line-height: 1.5;
-  color: #212529;
   background-color: transparent;
   background-color: transparent;
   border: solid transparent;
   border: solid transparent;
   border-width: 1px 0; }
   border-width: 1px 0; }
@@ -3375,10 +3371,6 @@
   #conversejs .custom-select.is-valid ~ .valid-feedback,
   #conversejs .custom-select.is-valid ~ .valid-feedback,
   #conversejs .custom-select.is-valid ~ .valid-tooltip {
   #conversejs .custom-select.is-valid ~ .valid-tooltip {
     display: block; }
     display: block; }
-.was-validated #conversejs .form-control-file:valid ~ .valid-feedback,
-.was-validated #conversejs .form-control-file:valid ~ .valid-tooltip, #conversejs .form-control-file.is-valid ~ .valid-feedback,
-#conversejs .form-control-file.is-valid ~ .valid-tooltip {
-  display: block; }
 .was-validated #conversejs .form-check-input:valid ~ .form-check-label, #conversejs .form-check-input.is-valid ~ .form-check-label {
 .was-validated #conversejs .form-check-input:valid ~ .form-check-label, #conversejs .form-check-input.is-valid ~ .form-check-label {
   color: #3AA569; }
   color: #3AA569; }
 .was-validated #conversejs .form-check-input:valid ~ .valid-feedback,
 .was-validated #conversejs .form-check-input:valid ~ .valid-feedback,
@@ -3443,10 +3435,6 @@
   #conversejs .custom-select.is-invalid ~ .invalid-feedback,
   #conversejs .custom-select.is-invalid ~ .invalid-feedback,
   #conversejs .custom-select.is-invalid ~ .invalid-tooltip {
   #conversejs .custom-select.is-invalid ~ .invalid-tooltip {
     display: block; }
     display: block; }
-.was-validated #conversejs .form-control-file:invalid ~ .invalid-feedback,
-.was-validated #conversejs .form-control-file:invalid ~ .invalid-tooltip, #conversejs .form-control-file.is-invalid ~ .invalid-feedback,
-#conversejs .form-control-file.is-invalid ~ .invalid-tooltip {
-  display: block; }
 .was-validated #conversejs .form-check-input:invalid ~ .form-check-label, #conversejs .form-check-input.is-invalid ~ .form-check-label {
 .was-validated #conversejs .form-check-input:invalid ~ .form-check-label, #conversejs .form-check-input.is-invalid ~ .form-check-label {
   color: #E77051; }
   color: #E77051; }
 .was-validated #conversejs .form-check-input:invalid ~ .invalid-feedback,
 .was-validated #conversejs .form-check-input:invalid ~ .invalid-feedback,
@@ -3499,8 +3487,7 @@
       vertical-align: middle; }
       vertical-align: middle; }
     #conversejs .form-inline .form-control-plaintext {
     #conversejs .form-inline .form-control-plaintext {
       display: inline-block; }
       display: inline-block; }
-    #conversejs .form-inline .input-group,
-    #conversejs .form-inline .custom-select {
+    #conversejs .form-inline .input-group {
       width: auto; }
       width: auto; }
     #conversejs .form-inline .form-check {
     #conversejs .form-inline .form-check {
       display: flex;
       display: flex;
@@ -3531,9 +3518,6 @@
   line-height: 1.5;
   line-height: 1.5;
   border-radius: 0.25rem;
   border-radius: 0.25rem;
   transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }
   transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }
-  @media screen and (prefers-reduced-motion: reduce) {
-    #conversejs .btn {
-      transition: none; } }
   #conversejs .btn:hover, #conversejs .btn:focus {
   #conversejs .btn:hover, #conversejs .btn:focus {
     text-decoration: none; }
     text-decoration: none; }
   #conversejs .btn:focus, #conversejs .btn.focus {
   #conversejs .btn:focus, #conversejs .btn.focus {
@@ -3882,8 +3866,7 @@
     border-color: transparent;
     border-color: transparent;
     box-shadow: none; }
     box-shadow: none; }
   #conversejs .btn-link:disabled, #conversejs .btn-link.disabled {
   #conversejs .btn-link:disabled, #conversejs .btn-link.disabled {
-    color: #6c757d;
-    pointer-events: none; }
+    color: #6c757d; }
 #conversejs .btn-lg, #conversejs .btn-group-lg > .btn {
 #conversejs .btn-lg, #conversejs .btn-group-lg > .btn {
   padding: 0.5rem 1rem;
   padding: 0.5rem 1rem;
   font-size: 1.25rem;
   font-size: 1.25rem;
@@ -3904,26 +3887,25 @@
 #conversejs input[type="button"].btn-block {
 #conversejs input[type="button"].btn-block {
   width: 100%; }
   width: 100%; }
 #conversejs .fade {
 #conversejs .fade {
+  opacity: 0;
   transition: opacity 0.15s linear; }
   transition: opacity 0.15s linear; }
-  @media screen and (prefers-reduced-motion: reduce) {
-    #conversejs .fade {
-      transition: none; } }
-  #conversejs .fade:not(.show) {
-    opacity: 0; }
-#conversejs .collapse:not(.show) {
+  #conversejs .fade.show {
+    opacity: 1; }
+#conversejs .collapse {
   display: none; }
   display: none; }
+  #conversejs .collapse.show {
+    display: block; }
+#conversejs tr.collapse.show {
+  display: table-row; }
+#conversejs tbody.collapse.show {
+  display: table-row-group; }
 #conversejs .collapsing {
 #conversejs .collapsing {
   position: relative;
   position: relative;
   height: 0;
   height: 0;
   overflow: hidden;
   overflow: hidden;
   transition: height 0.35s ease; }
   transition: height 0.35s ease; }
-  @media screen and (prefers-reduced-motion: reduce) {
-    #conversejs .collapsing {
-      transition: none; } }
 #conversejs .dropup,
 #conversejs .dropup,
-#conversejs .dropright,
-#conversejs .dropdown,
-#conversejs .dropleft {
+#conversejs .dropdown {
   position: relative; }
   position: relative; }
 #conversejs .dropdown-toggle::after {
 #conversejs .dropdown-toggle::after {
   display: inline-block;
   display: inline-block;
@@ -3956,12 +3938,7 @@
   background-clip: padding-box;
   background-clip: padding-box;
   border: 1px solid rgba(0, 0, 0, 0.15);
   border: 1px solid rgba(0, 0, 0, 0.15);
   border-radius: 0.25rem; }
   border-radius: 0.25rem; }
-#conversejs .dropdown-menu-right {
-  right: 0;
-  left: auto; }
 #conversejs .dropup .dropdown-menu {
 #conversejs .dropup .dropdown-menu {
-  top: auto;
-  bottom: 100%;
   margin-top: 0;
   margin-top: 0;
   margin-bottom: 0.125rem; }
   margin-bottom: 0.125rem; }
 #conversejs .dropup .dropdown-toggle::after {
 #conversejs .dropup .dropdown-toggle::after {
@@ -3978,9 +3955,6 @@
 #conversejs .dropup .dropdown-toggle:empty::after {
 #conversejs .dropup .dropdown-toggle:empty::after {
   margin-left: 0; }
   margin-left: 0; }
 #conversejs .dropright .dropdown-menu {
 #conversejs .dropright .dropdown-menu {
-  top: 0;
-  right: auto;
-  left: 100%;
   margin-top: 0;
   margin-top: 0;
   margin-left: 0.125rem; }
   margin-left: 0.125rem; }
 #conversejs .dropright .dropdown-toggle::after {
 #conversejs .dropright .dropdown-toggle::after {
@@ -3991,7 +3965,6 @@
   vertical-align: 0.255em;
   vertical-align: 0.255em;
   content: "";
   content: "";
   border-top: 0.3em solid transparent;
   border-top: 0.3em solid transparent;
-  border-right: 0;
   border-bottom: 0.3em solid transparent;
   border-bottom: 0.3em solid transparent;
   border-left: 0.3em solid; }
   border-left: 0.3em solid; }
 #conversejs .dropright .dropdown-toggle:empty::after {
 #conversejs .dropright .dropdown-toggle:empty::after {
@@ -3999,9 +3972,6 @@
 #conversejs .dropright .dropdown-toggle::after {
 #conversejs .dropright .dropdown-toggle::after {
   vertical-align: 0; }
   vertical-align: 0; }
 #conversejs .dropleft .dropdown-menu {
 #conversejs .dropleft .dropdown-menu {
-  top: 0;
-  right: 100%;
-  left: auto;
   margin-top: 0;
   margin-top: 0;
   margin-right: 0.125rem; }
   margin-right: 0.125rem; }
 #conversejs .dropleft .dropdown-toggle::after {
 #conversejs .dropleft .dropdown-toggle::after {
@@ -4027,9 +3997,6 @@
   margin-left: 0; }
   margin-left: 0; }
 #conversejs .dropleft .dropdown-toggle::before {
 #conversejs .dropleft .dropdown-toggle::before {
   vertical-align: 0; }
   vertical-align: 0; }
-#conversejs .dropdown-menu[x-placement^="top"], #conversejs .dropdown-menu[x-placement^="right"], #conversejs .dropdown-menu[x-placement^="bottom"], #conversejs .dropdown-menu[x-placement^="left"] {
-  right: auto;
-  bottom: auto; }
 #conversejs .dropdown-divider {
 #conversejs .dropdown-divider {
   height: 0;
   height: 0;
   margin: 0.5rem 0;
   margin: 0.5rem 0;
@@ -4066,10 +4033,6 @@
   font-size: 0.875rem;
   font-size: 0.875rem;
   color: #6c757d;
   color: #6c757d;
   white-space: nowrap; }
   white-space: nowrap; }
-#conversejs .dropdown-item-text {
-  display: block;
-  padding: 0.25rem 1.5rem;
-  color: #212529; }
 #conversejs .btn-group,
 #conversejs .btn-group,
 #conversejs .btn-group-vertical {
 #conversejs .btn-group-vertical {
   position: relative;
   position: relative;
@@ -4115,10 +4078,8 @@
 #conversejs .dropdown-toggle-split {
 #conversejs .dropdown-toggle-split {
   padding-right: 0.5625rem;
   padding-right: 0.5625rem;
   padding-left: 0.5625rem; }
   padding-left: 0.5625rem; }
-  #conversejs .dropdown-toggle-split::after, .dropup #conversejs .dropdown-toggle-split::after, .dropright #conversejs .dropdown-toggle-split::after {
+  #conversejs .dropdown-toggle-split::after {
     margin-left: 0; }
     margin-left: 0; }
-  .dropleft #conversejs .dropdown-toggle-split::before {
-    margin-right: 0; }
 #conversejs .btn-sm + .dropdown-toggle-split, #conversejs .btn-group-sm > .btn + .dropdown-toggle-split {
 #conversejs .btn-sm + .dropdown-toggle-split, #conversejs .btn-group-sm > .btn + .dropdown-toggle-split {
   padding-right: 0.375rem;
   padding-right: 0.375rem;
   padding-left: 0.375rem; }
   padding-left: 0.375rem; }
@@ -4194,10 +4155,10 @@
   #conversejs .input-group > .custom-file {
   #conversejs .input-group > .custom-file {
     display: flex;
     display: flex;
     align-items: center; }
     align-items: center; }
-    #conversejs .input-group > .custom-file:not(:last-child) .custom-file-label, #conversejs .input-group > .custom-file:not(:last-child) .custom-file-label::after {
+    #conversejs .input-group > .custom-file:not(:last-child) .custom-file-label, #conversejs .input-group > .custom-file:not(:last-child) .custom-file-label::before {
       border-top-right-radius: 0;
       border-top-right-radius: 0;
       border-bottom-right-radius: 0; }
       border-bottom-right-radius: 0; }
-    #conversejs .input-group > .custom-file:not(:first-child) .custom-file-label {
+    #conversejs .input-group > .custom-file:not(:first-child) .custom-file-label, #conversejs .input-group > .custom-file:not(:first-child) .custom-file-label::before {
       border-top-left-radius: 0;
       border-top-left-radius: 0;
       border-bottom-left-radius: 0; }
       border-bottom-left-radius: 0; }
 #conversejs .input-group-prepend,
 #conversejs .input-group-prepend,
@@ -4278,12 +4239,11 @@
     #conversejs .custom-control-input:disabled ~ .custom-control-label::before {
     #conversejs .custom-control-input:disabled ~ .custom-control-label::before {
       background-color: #e9ecef; }
       background-color: #e9ecef; }
 #conversejs .custom-control-label {
 #conversejs .custom-control-label {
-  position: relative;
   margin-bottom: 0; }
   margin-bottom: 0; }
   #conversejs .custom-control-label::before {
   #conversejs .custom-control-label::before {
     position: absolute;
     position: absolute;
     top: 0.25rem;
     top: 0.25rem;
-    left: -1.5rem;
+    left: 0;
     display: block;
     display: block;
     width: 1rem;
     width: 1rem;
     height: 1rem;
     height: 1rem;
@@ -4294,7 +4254,7 @@
   #conversejs .custom-control-label::after {
   #conversejs .custom-control-label::after {
     position: absolute;
     position: absolute;
     top: 0.25rem;
     top: 0.25rem;
-    left: -1.5rem;
+    left: 0;
     display: block;
     display: block;
     width: 1rem;
     width: 1rem;
     height: 1rem;
     height: 1rem;
@@ -4376,10 +4336,10 @@
   height: calc(2.25rem + 2px);
   height: calc(2.25rem + 2px);
   margin: 0;
   margin: 0;
   opacity: 0; }
   opacity: 0; }
-  #conversejs .custom-file-input:focus ~ .custom-file-label {
+  #conversejs .custom-file-input:focus ~ .custom-file-control {
     border-color: #7db3cd;
     border-color: #7db3cd;
     box-shadow: 0 0 0 0.2rem rgba(56, 117, 146, 0.25); }
     box-shadow: 0 0 0 0.2rem rgba(56, 117, 146, 0.25); }
-    #conversejs .custom-file-input:focus ~ .custom-file-label::after {
+    #conversejs .custom-file-input:focus ~ .custom-file-control::before {
       border-color: #7db3cd; }
       border-color: #7db3cd; }
   #conversejs .custom-file-input:lang(en) ~ .custom-file-label::after {
   #conversejs .custom-file-input:lang(en) ~ .custom-file-label::after {
     content: "Browse"; }
     content: "Browse"; }
@@ -4403,7 +4363,7 @@
     bottom: 0;
     bottom: 0;
     z-index: 3;
     z-index: 3;
     display: block;
     display: block;
-    height: 2.25rem;
+    height: calc(calc(2.25rem + 2px) - 1px * 2);
     padding: 0.375rem 0.75rem;
     padding: 0.375rem 0.75rem;
     line-height: 1.5;
     line-height: 1.5;
     color: #495057;
     color: #495057;
@@ -4411,83 +4371,6 @@
     background-color: #e9ecef;
     background-color: #e9ecef;
     border-left: 1px solid #ced4da;
     border-left: 1px solid #ced4da;
     border-radius: 0 0.25rem 0.25rem 0; }
     border-radius: 0 0.25rem 0.25rem 0; }
-#conversejs .custom-range {
-  width: 100%;
-  padding-left: 0;
-  background-color: transparent;
-  appearance: none; }
-  #conversejs .custom-range:focus {
-    outline: none; }
-  #conversejs .custom-range::-moz-focus-outer {
-    border: 0; }
-  #conversejs .custom-range::-webkit-slider-thumb {
-    width: 1rem;
-    height: 1rem;
-    margin-top: -0.25rem;
-    background-color: #387592;
-    border: 0;
-    border-radius: 1rem;
-    appearance: none; }
-    #conversejs .custom-range::-webkit-slider-thumb:focus {
-      outline: none;
-      box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(56, 117, 146, 0.25); }
-    #conversejs .custom-range::-webkit-slider-thumb:active {
-      background-color: #a1c9db; }
-  #conversejs .custom-range::-webkit-slider-runnable-track {
-    width: 100%;
-    height: 0.5rem;
-    color: transparent;
-    cursor: pointer;
-    background-color: #dee2e6;
-    border-color: transparent;
-    border-radius: 1rem; }
-  #conversejs .custom-range::-moz-range-thumb {
-    width: 1rem;
-    height: 1rem;
-    background-color: #387592;
-    border: 0;
-    border-radius: 1rem;
-    appearance: none; }
-    #conversejs .custom-range::-moz-range-thumb:focus {
-      outline: none;
-      box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(56, 117, 146, 0.25); }
-    #conversejs .custom-range::-moz-range-thumb:active {
-      background-color: #a1c9db; }
-  #conversejs .custom-range::-moz-range-track {
-    width: 100%;
-    height: 0.5rem;
-    color: transparent;
-    cursor: pointer;
-    background-color: #dee2e6;
-    border-color: transparent;
-    border-radius: 1rem; }
-  #conversejs .custom-range::-ms-thumb {
-    width: 1rem;
-    height: 1rem;
-    background-color: #387592;
-    border: 0;
-    border-radius: 1rem;
-    appearance: none; }
-    #conversejs .custom-range::-ms-thumb:focus {
-      outline: none;
-      box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(56, 117, 146, 0.25); }
-    #conversejs .custom-range::-ms-thumb:active {
-      background-color: #a1c9db; }
-  #conversejs .custom-range::-ms-track {
-    width: 100%;
-    height: 0.5rem;
-    color: transparent;
-    cursor: pointer;
-    background-color: transparent;
-    border-color: transparent;
-    border-width: 0.5rem; }
-  #conversejs .custom-range::-ms-fill-lower {
-    background-color: #dee2e6;
-    border-radius: 1rem; }
-  #conversejs .custom-range::-ms-fill-upper {
-    margin-right: 15px;
-    background-color: #dee2e6;
-    border-radius: 1rem; }
 #conversejs .card {
 #conversejs .card {
   position: relative;
   position: relative;
   display: flex;
   display: flex;
@@ -4633,24 +4516,10 @@
 @media (min-width: 576px) {
 @media (min-width: 576px) {
   #conversejs .card-columns {
   #conversejs .card-columns {
     column-count: 3;
     column-count: 3;
-    column-gap: 1.25rem;
-    orphans: 1;
-    widows: 1; }
+    column-gap: 1.25rem; }
     #conversejs .card-columns .card {
     #conversejs .card-columns .card {
       display: inline-block;
       display: inline-block;
       width: 100%; } }
       width: 100%; } }
-#conversejs .accordion .card:not(:first-of-type):not(:last-of-type) {
-  border-bottom: 0;
-  border-radius: 0; }
-#conversejs .accordion .card:not(:first-of-type) .card-header:first-child {
-  border-radius: 0; }
-#conversejs .accordion .card:first-of-type {
-  border-bottom: 0;
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 0; }
-#conversejs .accordion .card:last-of-type {
-  border-top-left-radius: 0;
-  border-top-right-radius: 0; }
 #conversejs .breadcrumb {
 #conversejs .breadcrumb {
   display: flex;
   display: flex;
   flex-wrap: wrap;
   flex-wrap: wrap;
@@ -4659,13 +4528,12 @@
   list-style: none;
   list-style: none;
   background-color: #e9ecef;
   background-color: #e9ecef;
   border-radius: 0.25rem; }
   border-radius: 0.25rem; }
-#conversejs .breadcrumb-item + .breadcrumb-item {
-  padding-left: 0.5rem; }
-  #conversejs .breadcrumb-item + .breadcrumb-item::before {
-    display: inline-block;
-    padding-right: 0.5rem;
-    color: #6c757d;
-    content: "/"; }
+#conversejs .breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+  color: #6c757d;
+  content: "/"; }
 #conversejs .breadcrumb-item + .breadcrumb-item:hover::before {
 #conversejs .breadcrumb-item + .breadcrumb-item:hover::before {
   text-decoration: underline; }
   text-decoration: underline; }
 #conversejs .breadcrumb-item + .breadcrumb-item:hover::before {
 #conversejs .breadcrumb-item + .breadcrumb-item:hover::before {
@@ -5005,9 +4873,6 @@
   .modal.fade #conversejs .modal-dialog {
   .modal.fade #conversejs .modal-dialog {
     transition: transform 0.3s ease-out;
     transition: transform 0.3s ease-out;
     transform: translate(0, -25%); }
     transform: translate(0, -25%); }
-    @media screen and (prefers-reduced-motion: reduce) {
-      .modal.fade #conversejs .modal-dialog {
-        transition: none; } }
   .modal.show #conversejs .modal-dialog {
   .modal.show #conversejs .modal-dialog {
     transform: translate(0, 0); }
     transform: translate(0, 0); }
 #conversejs .modal-dialog-centered {
 #conversejs .modal-dialog-centered {
@@ -5563,16 +5428,6 @@
   flex-wrap: nowrap !important; }
   flex-wrap: nowrap !important; }
 #conversejs .flex-wrap-reverse {
 #conversejs .flex-wrap-reverse {
   flex-wrap: wrap-reverse !important; }
   flex-wrap: wrap-reverse !important; }
-#conversejs .flex-fill {
-  flex: 1 1 auto !important; }
-#conversejs .flex-grow-0 {
-  flex-grow: 0 !important; }
-#conversejs .flex-grow-1 {
-  flex-grow: 1 !important; }
-#conversejs .flex-shrink-0 {
-  flex-shrink: 0 !important; }
-#conversejs .flex-shrink-1 {
-  flex-shrink: 1 !important; }
 #conversejs .justify-content-start {
 #conversejs .justify-content-start {
   justify-content: flex-start !important; }
   justify-content: flex-start !important; }
 #conversejs .justify-content-end {
 #conversejs .justify-content-end {
@@ -5632,16 +5487,6 @@
     flex-wrap: nowrap !important; }
     flex-wrap: nowrap !important; }
   #conversejs .flex-sm-wrap-reverse {
   #conversejs .flex-sm-wrap-reverse {
     flex-wrap: wrap-reverse !important; }
     flex-wrap: wrap-reverse !important; }
-  #conversejs .flex-sm-fill {
-    flex: 1 1 auto !important; }
-  #conversejs .flex-sm-grow-0 {
-    flex-grow: 0 !important; }
-  #conversejs .flex-sm-grow-1 {
-    flex-grow: 1 !important; }
-  #conversejs .flex-sm-shrink-0 {
-    flex-shrink: 0 !important; }
-  #conversejs .flex-sm-shrink-1 {
-    flex-shrink: 1 !important; }
   #conversejs .justify-content-sm-start {
   #conversejs .justify-content-sm-start {
     justify-content: flex-start !important; }
     justify-content: flex-start !important; }
   #conversejs .justify-content-sm-end {
   #conversejs .justify-content-sm-end {
@@ -5701,16 +5546,6 @@
     flex-wrap: nowrap !important; }
     flex-wrap: nowrap !important; }
   #conversejs .flex-md-wrap-reverse {
   #conversejs .flex-md-wrap-reverse {
     flex-wrap: wrap-reverse !important; }
     flex-wrap: wrap-reverse !important; }
-  #conversejs .flex-md-fill {
-    flex: 1 1 auto !important; }
-  #conversejs .flex-md-grow-0 {
-    flex-grow: 0 !important; }
-  #conversejs .flex-md-grow-1 {
-    flex-grow: 1 !important; }
-  #conversejs .flex-md-shrink-0 {
-    flex-shrink: 0 !important; }
-  #conversejs .flex-md-shrink-1 {
-    flex-shrink: 1 !important; }
   #conversejs .justify-content-md-start {
   #conversejs .justify-content-md-start {
     justify-content: flex-start !important; }
     justify-content: flex-start !important; }
   #conversejs .justify-content-md-end {
   #conversejs .justify-content-md-end {
@@ -5770,16 +5605,6 @@
     flex-wrap: nowrap !important; }
     flex-wrap: nowrap !important; }
   #conversejs .flex-lg-wrap-reverse {
   #conversejs .flex-lg-wrap-reverse {
     flex-wrap: wrap-reverse !important; }
     flex-wrap: wrap-reverse !important; }
-  #conversejs .flex-lg-fill {
-    flex: 1 1 auto !important; }
-  #conversejs .flex-lg-grow-0 {
-    flex-grow: 0 !important; }
-  #conversejs .flex-lg-grow-1 {
-    flex-grow: 1 !important; }
-  #conversejs .flex-lg-shrink-0 {
-    flex-shrink: 0 !important; }
-  #conversejs .flex-lg-shrink-1 {
-    flex-shrink: 1 !important; }
   #conversejs .justify-content-lg-start {
   #conversejs .justify-content-lg-start {
     justify-content: flex-start !important; }
     justify-content: flex-start !important; }
   #conversejs .justify-content-lg-end {
   #conversejs .justify-content-lg-end {
@@ -5839,16 +5664,6 @@
     flex-wrap: nowrap !important; }
     flex-wrap: nowrap !important; }
   #conversejs .flex-xl-wrap-reverse {
   #conversejs .flex-xl-wrap-reverse {
     flex-wrap: wrap-reverse !important; }
     flex-wrap: wrap-reverse !important; }
-  #conversejs .flex-xl-fill {
-    flex: 1 1 auto !important; }
-  #conversejs .flex-xl-grow-0 {
-    flex-grow: 0 !important; }
-  #conversejs .flex-xl-grow-1 {
-    flex-grow: 1 !important; }
-  #conversejs .flex-xl-shrink-0 {
-    flex-shrink: 0 !important; }
-  #conversejs .flex-xl-shrink-1 {
-    flex-shrink: 1 !important; }
   #conversejs .justify-content-xl-start {
   #conversejs .justify-content-xl-start {
     justify-content: flex-start !important; }
     justify-content: flex-start !important; }
   #conversejs .justify-content-xl-end {
   #conversejs .justify-content-xl-end {
@@ -5962,6 +5777,7 @@
   overflow: hidden;
   overflow: hidden;
   clip: rect(0, 0, 0, 0);
   clip: rect(0, 0, 0, 0);
   white-space: nowrap;
   white-space: nowrap;
+  clip-path: inset(50%);
   border: 0; }
   border: 0; }
 #conversejs .sr-only-focusable:active, #conversejs .sr-only-focusable:focus {
 #conversejs .sr-only-focusable:active, #conversejs .sr-only-focusable:focus {
   position: static;
   position: static;
@@ -5969,15 +5785,8 @@
   height: auto;
   height: auto;
   overflow: visible;
   overflow: visible;
   clip: auto;
   clip: auto;
-  white-space: normal; }
-#conversejs .shadow-sm {
-  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; }
-#conversejs .shadow {
-  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; }
-#conversejs .shadow-lg {
-  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; }
-#conversejs .shadow-none {
-  box-shadow: none !important; }
+  white-space: normal;
+  clip-path: none; }
 #conversejs .w-25 {
 #conversejs .w-25 {
   width: 25% !important; }
   width: 25% !important; }
 #conversejs .w-50 {
 #conversejs .w-50 {
@@ -5986,8 +5795,6 @@
   width: 75% !important; }
   width: 75% !important; }
 #conversejs .w-100 {
 #conversejs .w-100 {
   width: 100% !important; }
   width: 100% !important; }
-#conversejs .w-auto {
-  width: auto !important; }
 #conversejs .h-25 {
 #conversejs .h-25 {
   height: 25% !important; }
   height: 25% !important; }
 #conversejs .h-50 {
 #conversejs .h-50 {
@@ -5996,8 +5803,6 @@
   height: 75% !important; }
   height: 75% !important; }
 #conversejs .h-100 {
 #conversejs .h-100 {
   height: 100% !important; }
   height: 100% !important; }
-#conversejs .h-auto {
-  height: auto !important; }
 #conversejs .mw-100 {
 #conversejs .mw-100 {
   max-width: 100% !important; }
   max-width: 100% !important; }
 #conversejs .mh-100 {
 #conversejs .mh-100 {
@@ -6916,8 +6721,6 @@
   #conversejs .ml-xl-auto,
   #conversejs .ml-xl-auto,
   #conversejs .mx-xl-auto {
   #conversejs .mx-xl-auto {
     margin-left: auto !important; } }
     margin-left: auto !important; } }
-#conversejs .text-monospace {
-  font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
 #conversejs .text-justify {
 #conversejs .text-justify {
   text-align: justify !important; }
   text-align: justify !important; }
 #conversejs .text-nowrap {
 #conversejs .text-nowrap {
@@ -7008,14 +6811,8 @@
   color: #343a40 !important; }
   color: #343a40 !important; }
 #conversejs a.text-dark:hover, #conversejs a.text-dark:focus {
 #conversejs a.text-dark:hover, #conversejs a.text-dark:focus {
   color: #1d2124 !important; }
   color: #1d2124 !important; }
-#conversejs .text-body {
-  color: #212529 !important; }
 #conversejs .text-muted {
 #conversejs .text-muted {
   color: #6c757d !important; }
   color: #6c757d !important; }
-#conversejs .text-black-50 {
-  color: rgba(0, 0, 0, 0.5) !important; }
-#conversejs .text-white-50 {
-  color: rgba(255, 255, 255, 0.5) !important; }
 #conversejs .text-hide {
 #conversejs .text-hide {
   font: 0/0 a;
   font: 0/0 a;
   color: transparent;
   color: transparent;
@@ -8793,9 +8590,13 @@ body.reset {
       #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .mentioned,
       #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .mentioned,
       #conversejs .chatroom .box-flyout .chatroom-body .mentioned {
       #conversejs .chatroom .box-flyout .chatroom-body .mentioned {
         font-weight: bold; }
         font-weight: bold; }
-      #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .disconnect-msg,
-      #conversejs .chatroom .box-flyout .chatroom-body .disconnect-msg {
-        padding: 2em 2em 0 2em; }
+      #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .disconnect-container,
+      #conversejs .chatroom .box-flyout .chatroom-body .disconnect-container {
+        margin: 1em;
+        width: 100%; }
+        #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .disconnect-container h3.disconnect-msg,
+        #conversejs .chatroom .box-flyout .chatroom-body .disconnect-container h3.disconnect-msg {
+          padding-bottom: 1em; }
       #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .chat-area,
       #conversejs.converse-embedded .chatroom .box-flyout .chatroom-body .chat-area,
       #conversejs .chatroom .box-flyout .chatroom-body .chat-area {
       #conversejs .chatroom .box-flyout .chatroom-body .chat-area {
         display: flex;
         display: flex;

+ 54 - 24
dist/converse.js

@@ -71341,6 +71341,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
 
     if (message instanceof Error) {
     if (message instanceof Error) {
       message = message.stack;
       message = message.stack;
+    } else if (_.isElement(message)) {
+      message = message.outerHTML;
     }
     }
 
 
     const prefix = style ? '%c' : '';
     const prefix = style ? '%c' : '';
@@ -75985,13 +75987,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
            */
            */
           if (_.isNull(this.el.querySelector('.chat-area'))) {
           if (_.isNull(this.el.querySelector('.chat-area'))) {
             const container_el = this.el.querySelector('.chatroom-body');
             const container_el = this.el.querySelector('.chatroom-body');
-            container_el.innerHTML = tpl_chatarea({
+            container_el.insertAdjacentHTML('beforeend', tpl_chatarea({
               'label_message': __('Message'),
               'label_message': __('Message'),
               'label_send': __('Send'),
               'label_send': __('Send'),
               'show_send_button': _converse.show_send_button,
               'show_send_button': _converse.show_send_button,
               'show_toolbar': _converse.show_toolbar,
               'show_toolbar': _converse.show_toolbar,
               'unread_msgs': __('You have unread messages')
               'unread_msgs': __('You have unread messages')
-            });
+            }));
             container_el.insertAdjacentElement('beforeend', this.occupantsview.el);
             container_el.insertAdjacentElement('beforeend', this.occupantsview.el);
             this.renderToolbar(tpl_chatroom_toolbar);
             this.renderToolbar(tpl_chatroom_toolbar);
             this.content = this.el.querySelector('.chat-content');
             this.content = this.el.querySelector('.chat-content');
@@ -76674,15 +76676,22 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
           this.el.querySelector('.chatroom-form').addEventListener('submit', this.submitPassword.bind(this), false);
           this.el.querySelector('.chatroom-form').addEventListener('submit', this.submitPassword.bind(this), false);
         },
         },
 
 
-        showDisconnectMessage(msg) {
+        showDisconnectMessages(msgs) {
+          if (_.isString(msgs)) {
+            msgs = [msgs];
+          }
+
           u.hideElement(this.el.querySelector('.chat-area'));
           u.hideElement(this.el.querySelector('.chat-area'));
           u.hideElement(this.el.querySelector('.occupants'));
           u.hideElement(this.el.querySelector('.occupants'));
 
 
           _.each(this.el.querySelectorAll('.spinner'), u.removeElement);
           _.each(this.el.querySelectorAll('.spinner'), u.removeElement);
 
 
-          this.el.querySelector('.chatroom-body').insertAdjacentHTML('beforeend', tpl_chatroom_disconnect({
-            'disconnect_message': msg
-          }));
+          const container = this.el.querySelector('.disconnect-container');
+          container.innerHTML = tpl_chatroom_disconnect({
+            '_': _,
+            'disconnect_messages': msgs
+          });
+          u.showElement(container);
         },
         },
 
 
         getMessageFromStatus(stat, stanza, is_self) {
         getMessageFromStatus(stat, stanza, is_self) {
@@ -76781,16 +76790,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
            * information to the user.
            * information to the user.
            */
            */
           if (notification.disconnected) {
           if (notification.disconnected) {
-            this.showDisconnectMessage(notification.disconnection_message);
+            const messages = [];
+            messages.push(notification.disconnection_message);
 
 
             if (notification.actor) {
             if (notification.actor) {
-              this.showDisconnectMessage(__('This action was done by %1$s.', notification.actor));
+              messages.push(__('This action was done by %1$s.', notification.actor));
             }
             }
 
 
             if (notification.reason) {
             if (notification.reason) {
-              this.showDisconnectMessage(__('The reason given is: "%1$s".', notification.reason));
+              messages.push(__('The reason given is: "%1$s".', notification.reason));
             }
             }
 
 
+            this.showDisconnectMessages(messages);
             this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
             this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
             return;
             return;
           }
           }
@@ -76932,25 +76943,35 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
             if (!_.isNull(error.querySelector('not-authorized'))) {
             if (!_.isNull(error.querySelector('not-authorized'))) {
               this.renderPasswordForm();
               this.renderPasswordForm();
             } else if (!_.isNull(error.querySelector('registration-required'))) {
             } else if (!_.isNull(error.querySelector('registration-required'))) {
-              this.showDisconnectMessage(__('You are not on the member list of this room.'));
+              this.showDisconnectMessages(__('You are not on the member list of this room.'));
             } else if (!_.isNull(error.querySelector('forbidden'))) {
             } else if (!_.isNull(error.querySelector('forbidden'))) {
-              this.showDisconnectMessage(__('You have been banned from this room.'));
+              this.showDisconnectMessages(__('You have been banned from this room.'));
             }
             }
           } else if (error.getAttribute('type') === 'modify') {
           } else if (error.getAttribute('type') === 'modify') {
             if (!_.isNull(error.querySelector('jid-malformed'))) {
             if (!_.isNull(error.querySelector('jid-malformed'))) {
-              this.showDisconnectMessage(__('No nickname was specified.'));
+              this.showDisconnectMessages(__('No nickname was specified.'));
             }
             }
           } else if (error.getAttribute('type') === 'cancel') {
           } else if (error.getAttribute('type') === 'cancel') {
             if (!_.isNull(error.querySelector('not-allowed'))) {
             if (!_.isNull(error.querySelector('not-allowed'))) {
-              this.showDisconnectMessage(__('You are not allowed to create new rooms.'));
+              this.showDisconnectMessages(__('You are not allowed to create new rooms.'));
             } else if (!_.isNull(error.querySelector('not-acceptable'))) {
             } else if (!_.isNull(error.querySelector('not-acceptable'))) {
-              this.showDisconnectMessage(__("Your nickname doesn't conform to this room's policies."));
+              this.showDisconnectMessages(__("Your nickname doesn't conform to this room's policies."));
             } else if (!_.isNull(error.querySelector('conflict'))) {
             } else if (!_.isNull(error.querySelector('conflict'))) {
               this.onNicknameClash(presence);
               this.onNicknameClash(presence);
             } else if (!_.isNull(error.querySelector('item-not-found'))) {
             } else if (!_.isNull(error.querySelector('item-not-found'))) {
-              this.showDisconnectMessage(__("This room does not (yet) exist."));
+              this.showDisconnectMessages(__("This room does not (yet) exist."));
             } else if (!_.isNull(error.querySelector('service-unavailable'))) {
             } else if (!_.isNull(error.querySelector('service-unavailable'))) {
-              this.showDisconnectMessage(__("This room has reached its maximum number of occupants."));
+              this.showDisconnectMessages(__("This room has reached its maximum number of occupants."));
+            } else if (!_.isNull(error.querySelector('remote-server-not-found'))) {
+              const messages = [__("Remote server not found")];
+
+              const reason = _.get(error.querySelector('text'), 'textContent');
+
+              if (reason) {
+                messages.push(__('The explanation given is: "%1$s".', reason));
+              }
+
+              this.showDisconnectMessages(messages);
             }
             }
           }
           }
         },
         },
@@ -77564,7 +77585,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
 
             this.onPresence(stanza);
             this.onPresence(stanza);
             return true;
             return true;
-          }, Strophe.NS.MUC, 'presence', null, null, room_jid, {
+          }, null, 'presence', null, null, room_jid, {
             'ignoreNamespaceFragment': true,
             'ignoreNamespaceFragment': true,
             'matchBareFromJid': true
             'matchBareFromJid': true
           });
           });
@@ -77715,9 +77736,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
               this.parseRoomFeatures(stanza);
               this.parseRoomFeatures(stanza);
               resolve();
               resolve();
             }).catch(err => {
             }).catch(err => {
-              _converse.log(err, Strophe.LogLevel.ERROR);
+              _converse.log("Could not parse the room features", Strophe.LogLevel.WARN);
 
 
-              reject(new Error("Could not parse the room features"));
+              _converse.log(err, Strophe.LogLevel.WARN);
+
+              reject(err);
             });
             });
           });
           });
         },
         },
@@ -84149,7 +84172,7 @@ return __p
 var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
 var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
 module.exports = function(o) {
 module.exports = function(o) {
 var __t, __p = '';
 var __t, __p = '';
-__p += '<!-- src/templates/chatroom.html -->\n<div class="flyout box-flyout">\n    <div class="chat-head chat-head-chatroom row no-gutters"></div>\n    <div class="chat-body chatroom-body row no-gutters"></div>\n</div>\n';
+__p += '<!-- src/templates/chatroom.html -->\n<div class="flyout box-flyout">\n    <div class="chat-head chat-head-chatroom row no-gutters"></div>\n    <div class="chat-body chatroom-body row no-gutters">\n        <div class="disconnect-container hidden"></div>\n    </div>\n</div>\n';
 return __p
 return __p
 };
 };
 
 
@@ -84360,10 +84383,17 @@ return __p
 
 
 var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
 var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
 module.exports = function(o) {
 module.exports = function(o) {
-var __t, __p = '', __e = _.escape;
-__p += '<!-- src/templates/chatroom_disconnect.html -->\n<p class="disconnect-msg">' +
-__e(o.disconnect_message) +
-'</p>\n';
+var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
+function print() { __p += __j.call(arguments, '') }
+__p += '<!-- src/templates/chatroom_disconnect.html -->\n<div class="alert alert-danger">\n    <h3 class="alert-heading disconnect-msg">' +
+__e(o.disconnect_messages[0]) +
+'</h3>\n\n    ';
+ o._.forEach(o.disconnect_messages.slice(1), function (msg) { ;
+__p += '\n        <p class="disconnect-msg">' +
+__e(msg) +
+'</p>\n    ';
+ }); ;
+__p += '\n</div>\n';
 return __p
 return __p
 };
 };
 
 

+ 2 - 2
locale/af/LC_MESSAGES/converse.po

@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: Converse.js 0.4\n"
 "Project-Id-Version: Converse.js 0.4\n"
 "Report-Msgid-Bugs-To: \n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2018-05-17 11:19+0200\n"
 "POT-Creation-Date: 2018-05-17 11:19+0200\n"
-"PO-Revision-Date: 2018-03-05 16:35+0100\n"
+"PO-Revision-Date: 2018-07-02 11:29+0200\n"
 "Last-Translator: JC Brand <jc@opkode.com>\n"
 "Last-Translator: JC Brand <jc@opkode.com>\n"
 "Language-Team: Afrikaans <https://hosted.weblate.org/projects/conversejs/"
 "Language-Team: Afrikaans <https://hosted.weblate.org/projects/conversejs/"
 "translations/af/>\n"
 "translations/af/>\n"
@@ -1032,7 +1032,7 @@ msgstr "Hierdie aksie is uitgevoer deur %1$s."
 #: dist/converse-no-dependencies.js:29759
 #: dist/converse-no-dependencies.js:29759
 #, javascript-format
 #, javascript-format
 msgid "The reason given is: \"%1$s\"."
 msgid "The reason given is: \"%1$s\"."
-msgstr "Die gegewe rede is \"%1$s\"."
+msgstr "Die gegewe rede is: \"%1$s\"."
 
 
 #: dist/converse-no-dependencies.js:29781
 #: dist/converse-no-dependencies.js:29781
 #, fuzzy, javascript-format
 #, fuzzy, javascript-format

+ 6 - 2
sass/_chatrooms.scss

@@ -119,8 +119,12 @@
                 .mentioned {
                 .mentioned {
                     font-weight: bold;
                     font-weight: bold;
                 }
                 }
-                .disconnect-msg {
-                    padding: 2em 2em 0 2em;
+                .disconnect-container {
+                    margin: 1em;
+                    width: 100%;
+                    h3.disconnect-msg {
+                        padding-bottom: 1em;
+                    }
                 }
                 }
                 .chat-area {
                 .chat-area {
                     display: flex;
                     display: flex;

+ 21 - 13
spec/chatroom.js

@@ -1997,15 +1997,17 @@
                         .c('status').attrs({code:'307'}).nodeTree;
                         .c('status').attrs({code:'307'}).nodeTree;
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
 
 
-                    var view = _converse.chatboxviews.get('lounge@localhost');
+                    const view = _converse.chatboxviews.get('lounge@localhost');
                     expect($(view.el.querySelector('.chat-area')).is(':visible')).toBeFalsy();
                     expect($(view.el.querySelector('.chat-area')).is(':visible')).toBeFalsy();
                     expect($(view.el.querySelector('.occupants')).is(':visible')).toBeFalsy();
                     expect($(view.el.querySelector('.occupants')).is(':visible')).toBeFalsy();
-                    var $chat_body = $(view.el.querySelector('.chatroom-body'));
-                    expect($chat_body.find('.disconnect-msg').text()).toBe(
-                        'You have been kicked from this room'+
-                        'This action was done by Fluellen.'+
-                        'The reason given is: "Avaunt, you cullion!".'
-                    );
+                    const chat_body = view.el.querySelector('.chatroom-body');
+                    expect(chat_body.querySelectorAll('.disconnect-msg').length).toBe(3);
+                    expect(chat_body.querySelector('.disconnect-msg:first-child').textContent).toBe(
+                        'You have been kicked from this room');
+                    expect(chat_body.querySelector('.disconnect-msg:nth-child(2)').textContent).toBe(
+                        'This action was done by Fluellen.');
+                    expect(chat_body.querySelector('.disconnect-msg:nth-child(3)').textContent).toBe(
+                        'The reason given is: "Avaunt, you cullion!".');
                     done();
                     done();
                 });
                 });
             }));
             }));
@@ -2731,7 +2733,8 @@
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($(view.el).find('.chatroom-body p:last').text()).toBe('You are not on the member list of this room.');
+                    expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
+                        .toBe('You are not on the member list of this room.');
                     done();
                     done();
                 }).catch(_.partial(console.error, _));
                 }).catch(_.partial(console.error, _));
             }));
             }));
@@ -2754,7 +2757,8 @@
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($(view.el).find('.chatroom-body p:last').text()).toBe('You have been banned from this room.');
+                    expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
+                        .toBe('You have been banned from this room.');
                     done();
                     done();
                 }).catch(_.partial(console.error, _));
                 }).catch(_.partial(console.error, _));
             }));
             }));
@@ -2866,7 +2870,8 @@
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($(view.el).find('.chatroom-body p:last').text()).toBe('You are not allowed to create new rooms.');
+                    expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
+                        .toBe('You are not allowed to create new rooms.');
                     done();
                     done();
                 }).catch(_.partial(console.error, _));
                 }).catch(_.partial(console.error, _));
             }));
             }));
@@ -2889,7 +2894,8 @@
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($(view.el).find('.chatroom-body p:last').text()).toBe("Your nickname doesn't conform to this room's policies.");
+                    expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
+                        .toBe("Your nickname doesn't conform to this room's policies.");
                     done();
                     done();
                 }).catch(_.partial(console.error, _));
                 }).catch(_.partial(console.error, _));
             }));
             }));
@@ -2912,7 +2918,8 @@
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($(view.el).find('.chatroom-body p:last').text()).toBe("This room does not (yet) exist.");
+                    expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
+                        .toBe("This room does not (yet) exist.");
                     done();
                     done();
                 }).catch(_.partial(console.error, _));
                 }).catch(_.partial(console.error, _));
             }));
             }));
@@ -2935,7 +2942,8 @@
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     var view = _converse.chatboxviews.get('problematic@muc.localhost');
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     spyOn(view, 'showErrorMessage').and.callThrough();
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($(view.el).find('.chatroom-body p:last').text()).toBe("This room has reached its maximum number of occupants.");
+                    expect(view.el.querySelector('.chatroom-body .disconnect-container .disconnect-msg:last-child').textContent)
+                        .toBe("This room has reached its maximum number of occupants.");
                     done();
                     done();
                 }).catch(_.partial(console.error, _));
                 }).catch(_.partial(console.error, _));
             }));
             }));

+ 2 - 0
src/converse-core.js

@@ -227,6 +227,8 @@
         }
         }
         if (message instanceof Error) {
         if (message instanceof Error) {
             message = message.stack;
             message = message.stack;
+        } else if (_.isElement(message)) {
+            message = message.outerHTML;
         }
         }
         const prefix = style ? '%c' : '';
         const prefix = style ? '%c' : '';
         const logger = _.assign({
         const logger = _.assign({

+ 31 - 19
src/converse-muc-views.js

@@ -601,13 +601,13 @@
                      */
                      */
                     if (_.isNull(this.el.querySelector('.chat-area'))) {
                     if (_.isNull(this.el.querySelector('.chat-area'))) {
                         const container_el = this.el.querySelector('.chatroom-body');
                         const container_el = this.el.querySelector('.chatroom-body');
-                        container_el.innerHTML = tpl_chatarea({
+                        container_el.insertAdjacentHTML('beforeend', tpl_chatarea({
                             'label_message': __('Message'),
                             'label_message': __('Message'),
                             'label_send': __('Send'),
                             'label_send': __('Send'),
                             'show_send_button': _converse.show_send_button,
                             'show_send_button': _converse.show_send_button,
                             'show_toolbar': _converse.show_toolbar,
                             'show_toolbar': _converse.show_toolbar,
                             'unread_msgs': __('You have unread messages')
                             'unread_msgs': __('You have unread messages')
-                        });
+                        }));
                         container_el.insertAdjacentElement('beforeend', this.occupantsview.el);
                         container_el.insertAdjacentElement('beforeend', this.occupantsview.el);
                         this.renderToolbar(tpl_chatroom_toolbar);
                         this.renderToolbar(tpl_chatroom_toolbar);
                         this.content = this.el.querySelector('.chat-content');
                         this.content = this.el.querySelector('.chat-content');
@@ -1259,16 +1259,19 @@
                         'submit', this.submitPassword.bind(this), false);
                         'submit', this.submitPassword.bind(this), false);
                 },
                 },
 
 
-                showDisconnectMessage (msg) {
+                showDisconnectMessages (msgs) {
+                    if (_.isString(msgs)) {
+                        msgs = [msgs];
+                    }
                     u.hideElement(this.el.querySelector('.chat-area'));
                     u.hideElement(this.el.querySelector('.chat-area'));
                     u.hideElement(this.el.querySelector('.occupants'));
                     u.hideElement(this.el.querySelector('.occupants'));
                     _.each(this.el.querySelectorAll('.spinner'), u.removeElement);
                     _.each(this.el.querySelectorAll('.spinner'), u.removeElement);
-                    this.el.querySelector('.chatroom-body').insertAdjacentHTML(
-                        'beforeend',
-                        tpl_chatroom_disconnect({
-                            'disconnect_message': msg
-                        })
-                    );
+                    const container = this.el.querySelector('.disconnect-container');
+                    container.innerHTML = tpl_chatroom_disconnect({
+                        '_': _,
+                        'disconnect_messages': msgs
+                    })
+                    u.showElement(container);
                 },
                 },
 
 
                 getMessageFromStatus (stat, stanza, is_self) {
                 getMessageFromStatus (stat, stanza, is_self) {
@@ -1346,13 +1349,15 @@
                      * information to the user.
                      * information to the user.
                      */
                      */
                     if (notification.disconnected) {
                     if (notification.disconnected) {
-                        this.showDisconnectMessage(notification.disconnection_message);
+                        const messages = [];
+                        messages.push(notification.disconnection_message);
                         if (notification.actor) {
                         if (notification.actor) {
-                            this.showDisconnectMessage(__('This action was done by %1$s.', notification.actor));
+                            messages.push(__('This action was done by %1$s.', notification.actor));
                         }
                         }
                         if (notification.reason) {
                         if (notification.reason) {
-                            this.showDisconnectMessage(__('The reason given is: "%1$s".', notification.reason));
+                            messages.push(__('The reason given is: "%1$s".', notification.reason));
                         }
                         }
+                        this.showDisconnectMessages(messages);
                         this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
                         this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
                         return;
                         return;
                     }
                     }
@@ -1488,25 +1493,32 @@
                         if (!_.isNull(error.querySelector('not-authorized'))) {
                         if (!_.isNull(error.querySelector('not-authorized'))) {
                             this.renderPasswordForm();
                             this.renderPasswordForm();
                         } else if (!_.isNull(error.querySelector('registration-required'))) {
                         } else if (!_.isNull(error.querySelector('registration-required'))) {
-                            this.showDisconnectMessage(__('You are not on the member list of this room.'));
+                            this.showDisconnectMessages(__('You are not on the member list of this room.'));
                         } else if (!_.isNull(error.querySelector('forbidden'))) {
                         } else if (!_.isNull(error.querySelector('forbidden'))) {
-                            this.showDisconnectMessage(__('You have been banned from this room.'));
+                            this.showDisconnectMessages(__('You have been banned from this room.'));
                         }
                         }
                     } else if (error.getAttribute('type') === 'modify') {
                     } else if (error.getAttribute('type') === 'modify') {
                         if (!_.isNull(error.querySelector('jid-malformed'))) {
                         if (!_.isNull(error.querySelector('jid-malformed'))) {
-                            this.showDisconnectMessage(__('No nickname was specified.'));
+                            this.showDisconnectMessages(__('No nickname was specified.'));
                         }
                         }
                     } else if (error.getAttribute('type') === 'cancel') {
                     } else if (error.getAttribute('type') === 'cancel') {
                         if (!_.isNull(error.querySelector('not-allowed'))) {
                         if (!_.isNull(error.querySelector('not-allowed'))) {
-                            this.showDisconnectMessage(__('You are not allowed to create new rooms.'));
+                            this.showDisconnectMessages(__('You are not allowed to create new rooms.'));
                         } else if (!_.isNull(error.querySelector('not-acceptable'))) {
                         } else if (!_.isNull(error.querySelector('not-acceptable'))) {
-                            this.showDisconnectMessage(__("Your nickname doesn't conform to this room's policies."));
+                            this.showDisconnectMessages(__("Your nickname doesn't conform to this room's policies."));
                         } else if (!_.isNull(error.querySelector('conflict'))) {
                         } else if (!_.isNull(error.querySelector('conflict'))) {
                             this.onNicknameClash(presence);
                             this.onNicknameClash(presence);
                         } else if (!_.isNull(error.querySelector('item-not-found'))) {
                         } else if (!_.isNull(error.querySelector('item-not-found'))) {
-                            this.showDisconnectMessage(__("This room does not (yet) exist."));
+                            this.showDisconnectMessages(__("This room does not (yet) exist."));
                         } else if (!_.isNull(error.querySelector('service-unavailable'))) {
                         } else if (!_.isNull(error.querySelector('service-unavailable'))) {
-                            this.showDisconnectMessage(__("This room has reached its maximum number of occupants."));
+                            this.showDisconnectMessages(__("This room has reached its maximum number of occupants."));
+                        } else if (!_.isNull(error.querySelector('remote-server-not-found'))) {
+                            const messages = [__("Remote server not found")];
+                            const reason = _.get(error.querySelector('text'), 'textContent');
+                            if (reason) {
+                                messages.push(__('The explanation given is: "%1$s".', reason));
+                            }
+                            this.showDisconnectMessages(messages);
                         }
                         }
                     }
                     }
                 },
                 },

+ 3 - 2
src/converse-muc.js

@@ -331,8 +331,9 @@
                                 this.parseRoomFeatures(stanza);
                                 this.parseRoomFeatures(stanza);
                                 resolve()
                                 resolve()
                             }).catch((err) => {
                             }).catch((err) => {
-                                _converse.log(err, Strophe.LogLevel.ERROR);
-                                reject(new Error("Could not parse the room features"));
+                                _converse.log("Could not parse the room features", Strophe.LogLevel.WARN);
+                                _converse.log(err, Strophe.LogLevel.WARN);
+                                reject(err);
                             });
                             });
                     });
                     });
                 },
                 },

+ 3 - 1
src/templates/chatroom.html

@@ -1,4 +1,6 @@
 <div class="flyout box-flyout">
 <div class="flyout box-flyout">
     <div class="chat-head chat-head-chatroom row no-gutters"></div>
     <div class="chat-head chat-head-chatroom row no-gutters"></div>
-    <div class="chat-body chatroom-body row no-gutters"></div>
+    <div class="chat-body chatroom-body row no-gutters">
+        <div class="disconnect-container hidden"></div>
+    </div>
 </div>
 </div>

+ 7 - 1
src/templates/chatroom_disconnect.html

@@ -1 +1,7 @@
-<p class="disconnect-msg">{{{o.disconnect_message}}}</p>
+<div class="alert alert-danger">
+    <h3 class="alert-heading disconnect-msg">{{{o.disconnect_messages[0]}}}</h3>
+
+    {[ o._.forEach(o.disconnect_messages.slice(1), function (msg) { ]}
+        <p class="disconnect-msg">{{{msg}}}</p>
+    {[ }); ]}
+</div>