mirror of
				https://github.com/go-gitea/gitea
				synced 2025-09-28 03:28:13 +00:00 
			
		
		
		
	Unfortunately some of the suggested changes to #12095 introduced bugs which due to caching behaviour of sharedworkers were not caught on simple tests. These are as follows: * Changing from simple for loop to use includes here: ```js register(port) { if (!this.clients.includes(port)) return; this.clients.push(port); port.postMessage({ type: 'status', message: `registered to ${this.url}`, }); } ``` The additional `!` prevents any clients from being added and should read: ```js if (this.clients.includes(port)) return; ``` * Dropping the use of jQuery `$(...)` selection and using DOM `querySelector` here: ```js async function receiveUpdateCount(event) { try { const data = JSON.parse(event.data); const notificationCount = document.querySelector('.notification_count'); if (data.Count > 0) { notificationCount.classList.remove('hidden'); } else { notificationCount.classList.add('hidden'); } notificationCount.text() = `${data.Count}`; await updateNotificationTable(); } catch (error) { console.error(error, event); } } ``` Requires that `notificationCount.text()` be changed to use `textContent` instead. Signed-off-by: Andrew Thornton <art27@cantab.net>
		
			
				
	
	
		
			136 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| self.name = 'eventsource.sharedworker.js';
 | |
| 
 | |
| const sourcesByUrl = {};
 | |
| const sourcesByPort = {};
 | |
| 
 | |
| class Source {
 | |
|   constructor(url) {
 | |
|     this.url = url;
 | |
|     this.eventSource = new EventSource(url);
 | |
|     this.listening = {};
 | |
|     this.clients = [];
 | |
|     this.listen('open');
 | |
|     this.listen('logout');
 | |
|     this.listen('notification-count');
 | |
|     this.listen('error');
 | |
|   }
 | |
| 
 | |
|   register(port) {
 | |
|     if (this.clients.includes(port)) return;
 | |
| 
 | |
|     this.clients.push(port);
 | |
| 
 | |
|     port.postMessage({
 | |
|       type: 'status',
 | |
|       message: `registered to ${this.url}`,
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   deregister(port) {
 | |
|     const portIdx = this.clients.indexOf(port);
 | |
|     if (portIdx < 0) {
 | |
|       return this.clients.length;
 | |
|     }
 | |
|     this.clients.splice(portIdx, 1);
 | |
|     return this.clients.length;
 | |
|   }
 | |
| 
 | |
|   close() {
 | |
|     if (!this.eventSource) return;
 | |
| 
 | |
|     this.eventSource.close();
 | |
|     this.eventSource = null;
 | |
|   }
 | |
| 
 | |
|   listen(eventType) {
 | |
|     if (this.listening[eventType]) return;
 | |
|     this.listening[eventType] = true;
 | |
|     const self = this;
 | |
|     this.eventSource.addEventListener(eventType, (event) => {
 | |
|       self.notifyClients({
 | |
|         type: eventType,
 | |
|         data: event.data
 | |
|       });
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   notifyClients(event) {
 | |
|     for (const client of this.clients) {
 | |
|       client.postMessage(event);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   status(port) {
 | |
|     port.postMessage({
 | |
|       type: 'status',
 | |
|       message: `url: ${this.url} readyState: ${this.eventSource.readyState}`,
 | |
|     });
 | |
|   }
 | |
| }
 | |
| 
 | |
| self.onconnect = (e) => {
 | |
|   for (const port of e.ports) {
 | |
|     port.addEventListener('message', (event) => {
 | |
|       if (event.data.type === 'start') {
 | |
|         const url = event.data.url;
 | |
|         if (sourcesByUrl[url]) {
 | |
|           // we have a Source registered to this url
 | |
|           const source = sourcesByUrl[url];
 | |
|           source.register(port);
 | |
|           sourcesByPort[port] = source;
 | |
|           return;
 | |
|         }
 | |
|         let source = sourcesByPort[port];
 | |
|         if (source) {
 | |
|           if (source.eventSource && source.url === url) return;
 | |
| 
 | |
|           // How this has happened I don't understand...
 | |
|           // deregister from that source
 | |
|           const count = source.deregister(port);
 | |
|           // Clean-up
 | |
|           if (count === 0) {
 | |
|             source.close();
 | |
|             sourcesByUrl[source.url] = null;
 | |
|           }
 | |
|         }
 | |
|         // Create a new Source
 | |
|         source = new Source(url);
 | |
|         source.register(port);
 | |
|         sourcesByUrl[url] = source;
 | |
|         sourcesByPort[port] = source;
 | |
|       } else if (event.data.type === 'listen') {
 | |
|         const source = sourcesByPort[port];
 | |
|         source.listen(event.data.eventType);
 | |
|       } else if (event.data.type === 'close') {
 | |
|         const source = sourcesByPort[port];
 | |
| 
 | |
|         if (!source) return;
 | |
| 
 | |
|         const count = source.deregister(port);
 | |
|         if (count === 0) {
 | |
|           source.close();
 | |
|           sourcesByUrl[source.url] = null;
 | |
|           sourcesByPort[port] = null;
 | |
|         }
 | |
|       } else if (event.data.type === 'status') {
 | |
|         const source = sourcesByPort[port];
 | |
|         if (!source) {
 | |
|           port.postMessage({
 | |
|             type: 'status',
 | |
|             message: 'not connected',
 | |
|           });
 | |
|           return;
 | |
|         }
 | |
|         source.status(port);
 | |
|       } else {
 | |
|         // just send it back
 | |
|         port.postMessage({
 | |
|           type: 'error',
 | |
|           message: `received but don't know how to handle: ${event.data}`,
 | |
|         });
 | |
|       }
 | |
|     });
 | |
|     port.start();
 | |
|   }
 | |
| };
 |