UNPKG

9.26 kBJavaScriptView Raw
1"use strict";
2// *****************************************************************************
3// Copyright (C) 2018 TypeFox and others.
4//
5// This program and the accompanying materials are made available under the
6// terms of the Eclipse Public License v. 2.0 which is available at
7// http://www.eclipse.org/legal/epl-2.0.
8//
9// This Source Code may also be made available under the following Secondary
10// Licenses when the conditions for such availability set forth in the Eclipse
11// Public License v. 2.0 are satisfied: GNU General Public License, version 2
12// with the GNU Classpath Exception which is available at
13// https://www.gnu.org/software/classpath/license.html.
14//
15// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16// *****************************************************************************
17var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21 return c > 3 && r && Object.defineProperty(target, key, r), r;
22};
23var __metadata = (this && this.__metadata) || function (k, v) {
24 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25};
26var __param = (this && this.__param) || function (paramIndex, decorator) {
27 return function (target, key) { decorator(target, key, paramIndex); }
28};
29Object.defineProperty(exports, "__esModule", { value: true });
30exports.ApplicationConnectionStatusContribution = exports.FrontendConnectionStatusService = exports.AbstractConnectionStatusService = exports.PingService = exports.ConnectionStatusOptions = exports.ConnectionStatus = exports.ConnectionStatusService = void 0;
31const inversify_1 = require("inversify");
32const logger_1 = require("../common/logger");
33const event_1 = require("../common/event");
34const frontend_application_contribution_1 = require("./frontend-application-contribution");
35const status_bar_1 = require("./status-bar/status-bar");
36const ws_connection_provider_1 = require("./messaging/ws-connection-provider");
37const common_1 = require("../common");
38/**
39 * Service for listening on backend connection changes.
40 */
41exports.ConnectionStatusService = Symbol('ConnectionStatusService');
42/**
43 * The connection status.
44 */
45var ConnectionStatus;
46(function (ConnectionStatus) {
47 /**
48 * Connected to the backend.
49 */
50 ConnectionStatus[ConnectionStatus["ONLINE"] = 0] = "ONLINE";
51 /**
52 * The connection is lost between frontend and backend.
53 */
54 ConnectionStatus[ConnectionStatus["OFFLINE"] = 1] = "OFFLINE";
55})(ConnectionStatus = exports.ConnectionStatus || (exports.ConnectionStatus = {}));
56let ConnectionStatusOptions = class ConnectionStatusOptions {
57};
58ConnectionStatusOptions.DEFAULT = {
59 offlineTimeout: 5000,
60};
61ConnectionStatusOptions = __decorate([
62 (0, inversify_1.injectable)()
63], ConnectionStatusOptions);
64exports.ConnectionStatusOptions = ConnectionStatusOptions;
65exports.PingService = Symbol('PingService');
66let AbstractConnectionStatusService = class AbstractConnectionStatusService {
67 constructor(options = ConnectionStatusOptions.DEFAULT) {
68 this.options = options;
69 this.statusChangeEmitter = new event_1.Emitter();
70 this.connectionStatus = ConnectionStatus.ONLINE;
71 }
72 get onStatusChange() {
73 return this.statusChangeEmitter.event;
74 }
75 get currentStatus() {
76 return this.connectionStatus;
77 }
78 dispose() {
79 this.statusChangeEmitter.dispose();
80 }
81 updateStatus(success) {
82 const previousStatus = this.connectionStatus;
83 const newStatus = success ? ConnectionStatus.ONLINE : ConnectionStatus.OFFLINE;
84 if (previousStatus !== newStatus) {
85 this.connectionStatus = newStatus;
86 this.fireStatusChange(newStatus);
87 }
88 }
89 fireStatusChange(status) {
90 this.statusChangeEmitter.fire(status);
91 }
92};
93__decorate([
94 (0, inversify_1.inject)(logger_1.ILogger),
95 __metadata("design:type", Object)
96], AbstractConnectionStatusService.prototype, "logger", void 0);
97AbstractConnectionStatusService = __decorate([
98 (0, inversify_1.injectable)(),
99 __param(0, (0, inversify_1.inject)(ConnectionStatusOptions)),
100 __param(0, (0, inversify_1.optional)()),
101 __metadata("design:paramtypes", [ConnectionStatusOptions])
102], AbstractConnectionStatusService);
103exports.AbstractConnectionStatusService = AbstractConnectionStatusService;
104let FrontendConnectionStatusService = class FrontendConnectionStatusService extends AbstractConnectionStatusService {
105 init() {
106 this.wsConnectionProvider.onSocketDidOpen(() => {
107 this.updateStatus(true);
108 this.schedulePing();
109 });
110 this.wsConnectionProvider.onSocketDidClose(() => {
111 this.clearTimeout(this.scheduledPing);
112 this.updateStatus(false);
113 });
114 this.wsConnectionProvider.onIncomingMessageActivity(() => {
115 // natural activity
116 this.updateStatus(true);
117 this.schedulePing();
118 });
119 }
120 schedulePing() {
121 this.clearTimeout(this.scheduledPing);
122 this.scheduledPing = this.setTimeout(async () => {
123 await this.performPingRequest();
124 this.schedulePing();
125 }, this.options.offlineTimeout);
126 }
127 async performPingRequest() {
128 try {
129 await this.pingService.ping();
130 this.updateStatus(true);
131 }
132 catch (e) {
133 this.updateStatus(false);
134 await this.logger.error(e);
135 }
136 }
137 // eslint-disable-next-line @typescript-eslint/no-explicit-any
138 setTimeout(handler, timeout) {
139 return window.setTimeout(handler, timeout);
140 }
141 clearTimeout(handle) {
142 if (handle !== undefined) {
143 window.clearTimeout(handle);
144 }
145 }
146};
147__decorate([
148 (0, inversify_1.inject)(ws_connection_provider_1.WebSocketConnectionProvider),
149 __metadata("design:type", ws_connection_provider_1.WebSocketConnectionProvider)
150], FrontendConnectionStatusService.prototype, "wsConnectionProvider", void 0);
151__decorate([
152 (0, inversify_1.inject)(exports.PingService),
153 __metadata("design:type", Object)
154], FrontendConnectionStatusService.prototype, "pingService", void 0);
155__decorate([
156 (0, inversify_1.postConstruct)(),
157 __metadata("design:type", Function),
158 __metadata("design:paramtypes", []),
159 __metadata("design:returntype", void 0)
160], FrontendConnectionStatusService.prototype, "init", null);
161FrontendConnectionStatusService = __decorate([
162 (0, inversify_1.injectable)()
163], FrontendConnectionStatusService);
164exports.FrontendConnectionStatusService = FrontendConnectionStatusService;
165let ApplicationConnectionStatusContribution = class ApplicationConnectionStatusContribution extends frontend_application_contribution_1.DefaultFrontendApplicationContribution {
166 constructor(connectionStatusService, statusBar, logger) {
167 super();
168 this.connectionStatusService = connectionStatusService;
169 this.statusBar = statusBar;
170 this.logger = logger;
171 this.toDisposeOnOnline = new common_1.DisposableCollection();
172 this.statusbarId = 'connection-status';
173 this.connectionStatusService.onStatusChange(state => this.onStateChange(state));
174 }
175 onStateChange(state) {
176 switch (state) {
177 case ConnectionStatus.OFFLINE: {
178 this.handleOffline();
179 break;
180 }
181 case ConnectionStatus.ONLINE: {
182 this.handleOnline();
183 break;
184 }
185 }
186 }
187 handleOnline() {
188 this.toDisposeOnOnline.dispose();
189 }
190 handleOffline() {
191 this.statusBar.setElement(this.statusbarId, {
192 alignment: status_bar_1.StatusBarAlignment.LEFT,
193 text: common_1.nls.localize('theia/core/offline', 'Offline'),
194 tooltip: common_1.nls.localize('theia/localize/offlineTooltip', 'Cannot connect to backend.'),
195 priority: 5000
196 });
197 this.toDisposeOnOnline.push(common_1.Disposable.create(() => this.statusBar.removeElement(this.statusbarId)));
198 document.body.classList.add('theia-mod-offline');
199 this.toDisposeOnOnline.push(common_1.Disposable.create(() => document.body.classList.remove('theia-mod-offline')));
200 }
201};
202ApplicationConnectionStatusContribution = __decorate([
203 (0, inversify_1.injectable)(),
204 __param(0, (0, inversify_1.inject)(exports.ConnectionStatusService)),
205 __param(1, (0, inversify_1.inject)(status_bar_1.StatusBar)),
206 __param(2, (0, inversify_1.inject)(logger_1.ILogger)),
207 __metadata("design:paramtypes", [Object, Object, Object])
208], ApplicationConnectionStatusContribution);
209exports.ApplicationConnectionStatusContribution = ApplicationConnectionStatusContribution;
210//# sourceMappingURL=connection-status-service.js.map
\No newline at end of file