Skip to content

Commit

Permalink
feat: added heartbeat for mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaccoSordo committed Sep 21, 2024
1 parent 9d91c44 commit 9657046
Showing 1 changed file with 50 additions and 14 deletions.
64 changes: 50 additions & 14 deletions packages/beacon-core/src/utils/multi-tab-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Logger } from './Logger'
import { LocalStorage } from '../storage/LocalStorage'

type BCMessageType =
| 'HEARTBEAT'
| 'HEARTBEAT_ACK'
| 'RESPONSE'
| 'DISCONNECT'
| 'REQUEST_PAIRING'
Expand Down Expand Up @@ -40,7 +42,10 @@ export class MultiTabChannel {

private messageHandlers: {
[key in BCMessageType]?: (data: BCMessage) => void
} = {}
} = {
HEARTBEAT: this.heartbeatHandler.bind(this),
HEARTBEAT_ACK: this.heartbeatACKHandler.bind(this)
}

constructor(name: string, onBCMessageHandler: Function, onElectedLeaderHandler: Function) {
this.onBCMessageHandler = onBCMessageHandler
Expand All @@ -58,19 +63,7 @@ export class MultiTabChannel {
const newNeighborhood = !event.newValue ? this.neighborhood : JSON.parse(event.newValue)

if (newNeighborhood[0] !== this.leaderID) {
this.pendingACKs.set(
this.leaderID,
setTimeout(() => {
const neighborhood = Array.from(this.neighborhood)
this.leaderID = neighborhood[0]
if (neighborhood[0] !== this.id) {
return
}
this.isLeader = true
this.onElectedLeaderHandler()
logger.log('The current tab is the leader.')
}, timeout)
)
this.leaderElection()
} else {
clearTimeout(this.pendingACKs.get(this.leaderID))
}
Expand All @@ -96,6 +89,49 @@ export class MultiTabChannel {

window?.addEventListener('beforeunload', this.eventListeners[0])
this.channel.onmessage = this.eventListeners[1]

this.initHeartbeat()
}

private initHeartbeat() {
if (
this.isLeader ||
!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
) {
return
}

setInterval(() => {
this.leaderElection()
this.postMessage({ type: 'HEARTBEAT' })
}, timeout * 2)
}

private heartbeatHandler() {
if (!this.isLeader) {
return
}
this.postMessage({ type: 'HEARTBEAT_ACK' })
}

private heartbeatACKHandler() {
this.pendingACKs.delete(this.leaderID)
}

private leaderElection() {
this.pendingACKs.set(
this.leaderID,
setTimeout(() => {
const neighborhood = Array.from(this.neighborhood)
this.leaderID = neighborhood[0]
if (neighborhood[0] !== this.id) {
return
}
this.isLeader = true
this.onElectedLeaderHandler()
logger.log('The current tab is the leader.')
}, timeout)
)
}

private async onBeforeUnloadHandler() {
Expand Down

0 comments on commit 9657046

Please sign in to comment.