|  |  | @@ -1,44 +1,47 @@ | 
		
	
		
			
			|  |  |  | addEventListener('rpc-new', ({detail}) => { | 
		
	
		
			
			|  |  |  | const {uid, kind} = detail.value | 
		
	
		
			
			|  |  |  | if(kind === 'screen') { | 
		
	
		
			
			|  |  |  | const sender = ScreenShare.isSelf && ScreenShare.stream | 
		
	
		
			
			|  |  |  | const receiver = !ScreenShare.isSelf && ScreenShare.stream | 
		
	
		
			
			|  |  |  | const sender = ScreenShare.isSource && ScreenShare.stream | 
		
	
		
			
			|  |  |  | const receiver = !ScreenShare.isSource && ScreenShare.stream | 
		
	
		
			
			|  |  |  | signal({kind: 'rpc-setup', value: {uid, sender, receiver}}) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  | const ScreenShareConfig = { | 
		
	
		
			
			|  |  |  | view() { | 
		
	
		
			
			|  |  |  | const start = async () => { | 
		
	
		
			
			|  |  |  | await ScreenShare.getStream() | 
		
	
		
			
			|  |  |  | wire({kind: 'screen-share-start'}) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | const stop = () => wire({kind: 'screen-share-stop'}) | 
		
	
		
			
			|  |  |  | if (ScreenShare.source === null) { | 
		
	
		
			
			|  |  |  | return m('button', {onclick: start}, 'start screen sharing') | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else if (ScreenShare.isSelf) { | 
		
	
		
			
			|  |  |  | return m('button', {onclick: stop}, 'stop screen sharing') | 
		
	
		
			
			|  |  |  | if (ScreenShare.isOff) { | 
		
	
		
			
			|  |  |  | const onclick = ScreenShare.getStream | 
		
	
		
			
			|  |  |  | return m('button', {onclick}, 'start screen sharing') | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else { | 
		
	
		
			
			|  |  |  | return m('button[disabled]', `${ScreenShare.source} is screen sharing`) | 
		
	
		
			
			|  |  |  | const onclick = () => wire({kind: 'screen-stop'}) | 
		
	
		
			
			|  |  |  | return m('button', {onclick}, 'stop screen sharing') | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | const ScreenShare = { | 
		
	
		
			
			|  |  |  | source: null, | 
		
	
		
			
			|  |  |  | isSource: false, | 
		
	
		
			
			|  |  |  | stream: new MediaStream(), | 
		
	
		
			
			|  |  |  | get isSelf() { | 
		
	
		
			
			|  |  |  | return ScreenShare.source === State.username | 
		
	
		
			
			|  |  |  | get isOff() { | 
		
	
		
			
			|  |  |  | return ScreenShare.stream.getTracks().length === 0 | 
		
	
		
			
			|  |  |  | }, | 
		
	
		
			
			|  |  |  | async getStream() { | 
		
	
		
			
			|  |  |  | const stream = await navigator.mediaDevices.getDisplayMedia({}) | 
		
	
		
			
			|  |  |  | stream.getTracks() | 
		
	
		
			
			|  |  |  | await navigator.mediaDevices | 
		
	
		
			
			|  |  |  | .getDisplayMedia({}) | 
		
	
		
			
			|  |  |  | .then(stream => stream | 
		
	
		
			
			|  |  |  | .getTracks() | 
		
	
		
			
			|  |  |  | .forEach(tr => ScreenShare.stream.addTrack(tr, stream)) | 
		
	
		
			
			|  |  |  | ) | 
		
	
		
			
			|  |  |  | ScreenShare.isSource = true | 
		
	
		
			
			|  |  |  | State.others.forEach(target => { | 
		
	
		
			
			|  |  |  | signal({kind: 'rpc-needed', value: {kind: 'screen', target}}) | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  | m.redraw() | 
		
	
		
			
			|  |  |  | }, | 
		
	
		
			
			|  |  |  | async stopStream() { | 
		
	
		
			
			|  |  |  | ScreenShare.stream.getTracks() | 
		
	
		
			
			|  |  |  | .forEach(tr => tr.stop()) | 
		
	
		
			
			|  |  |  | ScreenShare.stream.getTracks().forEach(tr => tr.stop()) | 
		
	
		
			
			|  |  |  | ScreenShare.stream = new MediaStream() | 
		
	
		
			
			|  |  |  | ScreenShare.isSource = false | 
		
	
		
			
			|  |  |  | m.redraw() | 
		
	
		
			
			|  |  |  | }, | 
		
	
		
			
			|  |  |  | view() { | 
		
	
		
			
			|  |  |  | const style = { | 
		
	
	
		
			
			|  |  | @@ -48,36 +51,21 @@ const ScreenShare = { | 
		
	
		
			
			|  |  |  | fontFamily: 'monospace', | 
		
	
		
			
			|  |  |  | position: 'relative', | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return m('.screen-share', {style}, | 
		
	
		
			
			|  |  |  | ScreenShare.isSelf ? m('span', 'You are sharing your screen') : | 
		
	
		
			
			|  |  |  | ScreenShare.source ? m('video[playsinline][autoplay]', {srcObject: ScreenShare.stream}) | 
		
	
		
			
			|  |  |  | : [], | 
		
	
		
			
			|  |  |  | return ScreenShare.isOff ? [] : m('.screen-share', {style}, | 
		
	
		
			
			|  |  |  | m('video[playsinline][autoplay]', {srcObject: ScreenShare.stream}) | 
		
	
		
			
			|  |  |  | ) | 
		
	
		
			
			|  |  |  | }, | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | function sendScreen(target, stream) { | 
		
	
		
			
			|  |  |  | signal({kind: 'screen-start', value: {target, stream}}) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | addEventListener('screen-share-start', async ({detail: {source}}) => { | 
		
	
		
			
			|  |  |  | const isNew = ScreenShare.source === null | 
		
	
		
			
			|  |  |  | ScreenShare.source = source | 
		
	
		
			
			|  |  |  | if(isNew && ScreenShare.isSelf) { | 
		
	
		
			
			|  |  |  | State.others.forEach(user => sendScreen(user, ScreenShare.stream)) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  | addEventListener('screen-share-stop', () => { | 
		
	
		
			
			|  |  |  | addEventListener('screen-stop', () => { | 
		
	
		
			
			|  |  |  | ScreenShare.stopStream() | 
		
	
		
			
			|  |  |  | ScreenShare.source = null | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  | addEventListener('join', ({detail: {value: user}}) => { | 
		
	
		
			
			|  |  |  | if(ScreenShare.isSelf) { | 
		
	
		
			
			|  |  |  | wire({kind: 'screen-share-start', target: user}) | 
		
	
		
			
			|  |  |  | sendScreen(user, ScreenShare.stream) | 
		
	
		
			
			|  |  |  | if(ScreenShare.isSource) { | 
		
	
		
			
			|  |  |  | signal({kind: 'rpc-needed', value: {kind: 'screen', target: user}}) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  | addEventListener('load', () => { | 
		
	
		
			
			|  |  |  | doNotLog.add('screen-share-start') | 
		
	
		
			
			|  |  |  | doNotLog.add('screen-share-stop') | 
		
	
		
			
			|  |  |  | doNotLog.add('screen-stop') | 
		
	
		
			
			|  |  |  | Headers.push([ScreenShareConfig]) | 
		
	
		
			
			|  |  |  | Apps.push([ScreenShare, {key: 'screen-share-container'}]) | 
		
	
		
			
			|  |  |  | }) |