FEATURE: Offline indicator controlled by message-bus connectivity (#21324)

This commit is contained in:
Mark VanLandingham 2023-05-01 12:41:30 -05:00 committed by GitHub
parent 685e1de3ea
commit b1da670898
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 95 additions and 14 deletions

View File

@ -0,0 +1,10 @@
{{#if this.showing}}
<div class="offline-indicator">
<span>{{i18n "offline_indicator.no_internet"}}</span>
<DButton
@label="offline_indicator.refresh_page"
@display="link"
@action={{this.refresh}}
/>
</div>
{{/if}}

View File

@ -0,0 +1,16 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
export default class OfflineIndicator extends Component {
@service messageBusConnectivity;
get showing() {
return !this.messageBusConnectivity.connected;
}
@action
refresh() {
window.location.reload(true);
}
}

View File

@ -5,23 +5,16 @@ import { handleLogoff } from "discourse/lib/ajax";
import userPresent, { onPresenceChange } from "discourse/lib/user-presence";
const LONG_POLL_AFTER_UNSEEN_TIME = 1200000; // 20 minutes
const CONNECTIVITY_ERROR_CLASS = "message-bus-offline";
function updateConnectivityIndicator(stat) {
if (stat === "error") {
document.documentElement.classList.add(CONNECTIVITY_ERROR_CLASS);
} else {
document.documentElement.classList.remove(CONNECTIVITY_ERROR_CLASS);
}
}
function ajax(opts) {
function ajax(opts, messageBusConnectivity) {
if (opts.complete) {
const oldComplete = opts.complete;
opts.complete = function (xhr, stat) {
handleLogoff(xhr);
oldComplete(xhr, stat);
updateConnectivityIndicator(stat);
messageBusConnectivity.setConnectivity(
stat === "abort" || xhr.readyState === 4
);
};
} else {
opts.complete = handleLogoff;
@ -42,7 +35,10 @@ export default {
const messageBus = container.lookup("service:message-bus"),
user = container.lookup("service:current-user"),
siteSettings = container.lookup("service:site-settings");
siteSettings = container.lookup("service:site-settings"),
messageBusConnectivity = container.lookup(
"service:message-bus-connectivity"
);
messageBus.alwaysLongPoll = !isProduction();
messageBus.shouldLongPollCallback = () =>
@ -97,7 +93,7 @@ export default {
if (userPresent()) {
opts.headers["Discourse-Present"] = "true";
}
return ajax(opts);
return ajax(opts, messageBusConnectivity);
};
} else {
messageBus.ajax = function (opts) {
@ -105,7 +101,7 @@ export default {
if (userPresent()) {
opts.headers["Discourse-Present"] = "true";
}
return ajax(opts);
return ajax(opts, messageBusConnectivity);
};
messageBus.baseUrl = getURL("/");

View File

@ -0,0 +1,16 @@
import Service from "@ember/service";
import { tracked } from "@glimmer/tracking";
const CONNECTIVITY_ERROR_CLASS = "message-bus-offline";
export default class MessageBusConnectivity extends Service {
@tracked connected = true;
setConnectivity(connected) {
this.connected = connected;
document.documentElement.classList.toggle(
CONNECTIVITY_ERROR_CLASS,
!connected
);
}
}

View File

@ -24,6 +24,7 @@
{{/if}}
<SoftwareUpdatePrompt />
<OfflineIndicator />
<PluginOutlet
@name="below-site-header"

View File

@ -22,6 +22,7 @@
@import "ignored-user-list";
@import "keyboard_shortcuts";
@import "navs";
@import "offline-indicator";
@import "pick-files-button";
@import "relative-time-picker";
@import "share-and-invite-modal";

View File

@ -0,0 +1,10 @@
.offline-indicator {
position: fixed;
top: var(--header-offset);
left: 50%;
transform: translate(-50%, 0);
padding: 0.5em 1em;
background-color: var(--primary-very-low);
border-radius: var(--d-nav-pill-border-radius);
z-index: z("header") - 10;
}

View File

@ -2065,6 +2065,10 @@ en:
intro: "Hello! Looks like youre enjoying the discussion, but you havent signed up for an account yet."
value_prop: "Tired of scrolling through the same posts? When you create an account youll always come back to where you left off. With an account you can also be notified of new replies, save bookmarks, and use likes to thank others. We can all work together to make this community great. :heart:"
offline_indicator:
no_internet: "No internet connection."
refresh_page: "Refresh page"
summary:
enabled_description: "You're viewing a summary of this topic: the most interesting posts as determined by the community."
description:

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
RSpec.describe "Network Disconnected", type: :system, js: true do
fab!(:current_user) { Fabricate(:user) }
def with_network_disconnected
page.driver.browser.network_conditions = { offline: true }
yield
page.driver.browser.network_conditions = { offline: false }
end
it "Message bus connectivity service adds class to DOM and displays offline indicator" do
sign_in(current_user)
visit("/c")
expect(page).to have_no_css("html.message-bus-offline")
expect(page).to have_no_css(".offline-indicator")
with_network_disconnected do
# Message bus connectivity services adds the disconnected class to the DOM
expect(page).to have_css("html.message-bus-offline")
# Offline indicator is rendered
expect(page).to have_css(".offline-indicator")
end
end
end