import {Visconnect} from './visconnect'; import {VisConnectUtil} from './util'; import {StrippedEvent} from './listener'; export class VisConnectUi { private cursorResetTimeout = 0; constructor(private visconnect: Visconnect, private element: Element) { this.addTemplate(); this.initiateCursors(); const protocol = this.visconnect.protocol; protocol.communication.onConnectionCallback = this.updateConnections.bind(this); protocol.onLoading = this.showLoadingScreen.bind(this); protocol.onDoneLoading = this.hideLoadingScreen.bind(this); protocol.communication.onLoading = this.showLoadingScreen.bind(this); protocol.communication.onDoneLoading = this.hideLoadingScreen.bind(this); protocol.communication.onFailure = this.onFailure.bind(this); this.showLoadingScreen('Setting up..'); this.updateConnections(); } initiateCursors() { this.element.addEventListener('mousemove', this.mouseMoved.bind(this)); const container = document.createElement('div'); container.id = 'visconnect-cursors'; document.body.appendChild(container); } getCursor(participant: string) { const elementId = `visconnect-cursor-${participant}`; let cursor = document.getElementById(elementId); if (!cursor) { const cursors = document.getElementById('visconnect-cursors')!; cursor = document.createElement('div'); cursor.style.background = VisConnectUtil.stringToHex(participant); cursor.style.width = '5px'; cursor.style.height = '5px'; cursor.style.position = 'absolute'; cursor.style.borderRadius = '3px'; cursor.style.pointerEvents = 'none'; cursor.id = elementId; cursors.appendChild(cursor); } return cursor; } mouseMoved(originalEvent: Event) { const event = originalEvent as MouseEvent & {collaboratorId: string}; const ownId = this.visconnect.protocol.communication.id; const collaborator = event['collaboratorId']; if (!collaborator || !ownId || ownId === collaborator) { return; } const cursor = this.getCursor(collaborator); cursor.style.left = `${event.clientX - 2}px`; cursor.style.top = `${event.clientY - 2}px`; } eventCancelled(event: StrippedEvent) { clearTimeout(this.cursorResetTimeout); let target: HTMLElement = document.querySelector(event.target) || document.body; target.style.setProperty('cursor', 'not-allowed', 'important'); this.cursorResetTimeout = window.setTimeout(() => { target.style.removeProperty('cursor'); }, 50); } updateConnections() { const connections = this.visconnect.protocol.communication.getNumberOfConnections(); const collaborators = connections - 1; if (collaborators > 0) { document.getElementById('visconnect-container')!.style.height = '70px'; document.getElementById('visconnect-collab-notice')!.style.display = 'inline'; document.getElementById('visconnect-collab-count')!.innerText = String(collaborators); } else { document.getElementById('visconnect-container')!.style.height = '50px'; document.getElementById('visconnect-collab-notice')!.style.display = 'none'; } } invite() { const communication = this.visconnect.protocol.communication; const leaderId = communication.leaderId; const logo = document.getElementById('visconnect-logo')!; const collabNotice = document.getElementById('visconnect-collab-notice')!; if (!leaderId) { const errorElement = document.getElementById('visconnect-not-ready')!; logo.style.display = 'none'; errorElement.style.display = 'inline'; setTimeout(() => { logo.style.display = 'block'; errorElement.style.display = 'none'; }, 1000); return; } let url = location.href.replace(/visconnectownid=[a-z0-9]+/gi, ''); if (leaderId === communication.id) { url += '?visconnectid=' + leaderId; } copyToClipboard(url); const inviteLinkCopied = document.getElementById('visconnect-link-copied')!; const collabNoticeDisplay = collabNotice.style.display; logo.style.display = 'none'; collabNotice.style.display = 'none'; inviteLinkCopied.style.display = 'inline'; setTimeout(() => { logo.style.display = 'block'; inviteLinkCopied.style.display = 'none'; collabNotice.style.display = collabNoticeDisplay; }, 1400); } onFailure(message: string) { console.log('Connection Failed.'); this.showLoadingScreen(message); document.getElementById('visconnect-container')!.style.display = 'none'; this.visconnect.stop(); } showLoadingScreen(message: string) { this.hideLoadingScreen(); const container = document.createElement('div'); container.id = 'visconnect-loadingscreen'; document.body.appendChild(container); container.innerHTML = `
VisConnect Loading:
${message}