feat(sync): Display the state of the connection to the users

This commit is contained in:
Alexis Métaireau 2024-10-25 12:25:35 +02:00
parent 6643fe0a2b
commit aac5185b16
No known key found for this signature in database
GPG key ID: 1C21B876828E5FF2
5 changed files with 64 additions and 31 deletions

View file

@ -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) {

View file

@ -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 =
'<span>' + this.sync.getNumberOfConnectedPeers() + '</span>'
if (connectedPeers !== 0 || !this.sync.websocketConnected) {
const connectedPeersCount = L.DomUtil.createButton(
'leaflet-control-connected-peers',
rightContainer,
''
)
if (this.sync.websocketConnected) {
connectedPeersCount.innerHTML =
'<span>' + this.sync.getNumberOfConnectedPeers() + '</span>'
hoverMessage = L._(
'{connectedPeers} peer(s) currently connected to this map',
{
connectedPeers: connectedPeers,
}
)
} else {
connectedPeersCount.innerHTML = '<span>' + L._('Disconnected') + '</span>'
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)

View file

@ -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 {

View file

@ -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,

View file

@ -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()