diff --git a/umap/static/umap/js/modules/sync/engine.js b/umap/static/umap/js/modules/sync/engine.js
index 9a3ef611..749a707f 100644
--- a/umap/static/umap/js/modules/sync/engine.js
+++ b/umap/static/umap/js/modules/sync/engine.js
@@ -48,7 +48,7 @@ const MAX_RECONNECT_DELAY = 32000;
* ```
*/
export class SyncEngine {
- constructor(map, urls, server) {
+ constructor(map, websocketTokenURI, websocketURI, server) {
this.updaters = {
map: new MapUpdater(map),
feature: new FeatureUpdater(map),
@@ -58,14 +58,12 @@ export class SyncEngine {
this._operations = new Operations()
this._server = server
- // Store URIs to avoid persisting the map
- // mainly to ensure separation of concerns.
- this._websocketTokenURI = urls.get('map_websocket_auth_token', {
- map_id: map.options.umap_id,
- })
- this._websocketURI = map.options.websocketURI
+ this._websocketTokenURI = websocketTokenURI
+ this._websocketURI = websocketURI
+
this._reconnectTimeout = null;
this._reconnectDelay = RECONNECT_DELAY;
+ this.websocketConnected = false;
}
/**
@@ -92,9 +90,13 @@ export class SyncEngine {
onConnection() {
this._reconnectTimeout = null;
this._reconnectDelay = RECONNECT_DELAY;
+ this.websocketConnected = true;
}
reconnect() {
+ this.websocketConnected = false;
+ this.updaters.map.update({ key: 'numberOfConnectedPeers' })
+
console.log("reconnecting in ", this._reconnectDelay, " ms")
this._reconnectTimeout = setTimeout(() => {
if (this._reconnectDelay < MAX_RECONNECT_DELAY) {
diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js
index c6e85e12..96847bd8 100644
--- a/umap/static/umap/js/umap.controls.js
+++ b/umap/static/umap/js/umap.controls.js
@@ -661,30 +661,43 @@ const ControlsMixin = {
})
}
- const connectedPeers = this.sync.getNumberOfConnectedPeers()
- if (connectedPeers !== 0) {
- const connectedPeersCount = L.DomUtil.createButton(
- 'leaflet-control-connected-peers',
- rightContainer,
- ''
- )
- L.DomEvent.on(connectedPeersCount, 'mouseover', () => {
- this.tooltip.open({
- content: L._('{connectedPeers} peer(s) currently connected to this map', {
- connectedPeers: connectedPeers,
- }),
- anchor: connectedPeersCount,
- position: 'bottom',
- delay: 500,
- duration: 5000,
- })
- })
+ if (this.options.syncEnabled) {
+ const connectedPeers = this.sync.getNumberOfConnectedPeers()
+ let hoverMessage = ''
- const updateConnectedPeersCount = () => {
- connectedPeersCount.innerHTML =
- '' + this.sync.getNumberOfConnectedPeers() + ''
+ if (connectedPeers !== 0 || !this.sync.websocketConnected) {
+ const connectedPeersCount = L.DomUtil.createButton(
+ 'leaflet-control-connected-peers',
+ rightContainer,
+ ''
+ )
+ if (this.sync.websocketConnected) {
+ connectedPeersCount.innerHTML =
+ '' + this.sync.getNumberOfConnectedPeers() + ''
+ hoverMessage = L._(
+ '{connectedPeers} peer(s) currently connected to this map',
+ {
+ connectedPeers: connectedPeers,
+ }
+ )
+ } else {
+ connectedPeersCount.innerHTML = '' + L._('Disconnected') + ''
+ connectedPeersCount.classList.add('disconnected')
+ hoverMessage = L._('Reconnecting in {seconds} seconds', {
+ seconds: this.sync._reconnectDelay / 1000,
+ })
+ }
+
+ L.DomEvent.on(connectedPeersCount, 'mouseover', () => {
+ this.tooltip.open({
+ content: hoverMessage,
+ anchor: connectedPeersCount,
+ position: 'bottom',
+ delay: 500,
+ duration: 5000,
+ })
+ })
}
- updateConnectedPeersCount()
}
this.help.getStartedLink(rightContainer)
diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js
index ccd94e15..0d51fcdd 100644
--- a/umap/static/umap/js/umap.js
+++ b/umap/static/umap/js/umap.js
@@ -68,7 +68,14 @@ U.Map = L.Map.extend({
this.server = new U.ServerRequest()
this.request = new U.Request()
- this.sync_engine = new U.SyncEngine(this, this.urls, this.server)
+ // Store URIs to avoid persisting the map
+ // mainly to ensure separation of concerns.
+ const websocketTokenURI = this.urls.get('map_websocket_auth_token', {
+ map_id: this.options.umap_id,
+ })
+ const websocketURI = this.options.websocketURI
+
+ this.sync_engine = new U.SyncEngine(this, websocketTokenURI, websocketURI, this.server)
this.sync = this.sync_engine.proxy(this)
this.initLoader()
@@ -206,7 +213,9 @@ U.Map = L.Map.extend({
},
initSyncEngine: async function () {
+ // This.options.websocketEnabled is set by the server admin
if (this.options.websocketEnabled === false) return
+ // This.options.syncEnabled is set by the user in the map settings
if (this.options.syncEnabled !== true) {
this.sync.stop()
} else {
diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css
index ce59df08..28bd63aa 100644
--- a/umap/static/umap/map.css
+++ b/umap/static/umap/map.css
@@ -518,6 +518,12 @@ ul.photon-autocomplete {
background-color: var(--color-lightCyan);
color: var(--color-dark);
}
+.leaflet-container .leaflet-control-connected-peers.disconnected,
+.leaflet-container .leaflet-control-connected-peers.disconnected:hover
+{
+ background-color: var(--color-red);
+ color: var(--color-darkGray);
+}
.leaflet-container .leaflet-control-edit-disable:before,
.leaflet-container .leaflet-control-edit-save:before,
diff --git a/umap/static/umap/unittests/sync.js b/umap/static/umap/unittests/sync.js
index 36d22b10..4d5a8e44 100644
--- a/umap/static/umap/unittests/sync.js
+++ b/umap/static/umap/unittests/sync.js
@@ -8,8 +8,11 @@ import { MapUpdater } from '../js/modules/sync/updaters.js'
import { SyncEngine, Operations } from '../js/modules/sync/engine.js'
describe('SyncEngine', () => {
+ const websocketTokenURI = 'http://localhost:8000/api/v1/maps/1/websocket_auth_token/'
+ const websocketURI = 'ws://localhost:8000/ws/maps/1/'
+
it('should initialize methods even before start', () => {
- const engine = new SyncEngine({})
+ const engine = new SyncEngine({}, websocketTokenURI, websocketURI, {})
engine.upsert()
engine.update()
engine.delete()