11import * as constants from './constants.js' ;
2+ import * as presence from './presence.js' ;
23import * as helper from './helper.js' ;
34
45export const CURSOR_UPDATE_THROTTLE_MS = 50 ;
@@ -515,9 +516,11 @@ export function ensureCollaborationLayerOnTop() {
515516}
516517
517518export function setupCollaborationLayer ( ) {
518- const workspace = constants . mutableRefs . BlocklyInstance . getMainWorkspace ( ) ;
519+ const workspace = constants . editorWorkspace ( ) ;
519520 if ( ! workspace ) return ;
520521
522+ if ( constants . mutableRefs . isViewer ) applyViewerWorkspace ( workspace ) ;
523+
521524 const newWorkspaceSvg = workspace . getParentSvg ( ) ;
522525 const workspaceGroup = newWorkspaceSvg ?. querySelector ( '.blocklyBlockCanvas' ) ;
523526
@@ -593,7 +596,7 @@ export function setupCollaborationLayer() {
593596
594597 if ( ! constants . mutableRefs . throttledMouseMoveHandler ) {
595598 constants . mutableRefs . throttledMouseMoveHandler = helper . throttle ( ( e ) => {
596- const currentWorkspace = constants . mutableRefs . BlocklyInstance . getMainWorkspace ( ) ;
599+ const currentWorkspace = constants . editorWorkspace ( ) ;
597600 if ( ! currentWorkspace || ! currentWorkspace . getParentSvg ( ) || ! currentWorkspace . getCanvas ( ) || ! constants . mutableRefs . yjsAwarenessInstance ) return ;
598601 if ( e . target ?. closest ( '.blocklyFlyout' ) || currentWorkspace . isFlyout ) return ;
599602
@@ -659,7 +662,7 @@ export function setupCollaborationLayer() {
659662 }
660663
661664 if ( constants . mutableRefs . yjsAwarenessInstance && constants . mutableRefs . collaborationLayerGroup ) {
662- const states = constants . mutableRefs . yjsAwarenessInstance . getStates ( ) ;
665+ const states = presence . collabStates ( ) ;
663666 const localClientID = constants . mutableRefs . yjsAwarenessInstance . clientID ;
664667 states . forEach ( ( state , clientID ) => {
665668 if ( clientID === localClientID ) return ;
@@ -672,14 +675,6 @@ export function setupCollaborationLayer() {
672675 }
673676}
674677
675- let backpackInsertOverride = false ;
676- window . handleBackpackCollaboratorOverride = function ( ) {
677- backpackInsertOverride = true ;
678- setTimeout ( ( ) => {
679- backpackInsertOverride = false ;
680- } , 1000 ) ;
681- } ;
682-
683678let undoRedoOverride = false ;
684679export function setUndoRedoOverride ( ) {
685680 undoRedoOverride = true ;
@@ -691,7 +686,7 @@ export function setUndoRedoOverride() {
691686export function updateUserMenuBarIcons ( ) {
692687 if ( ! constants . mutableRefs . yjsAwarenessInstance || ! constants . mutableRefs . userIconContainer ) return ;
693688
694- const states = constants . mutableRefs . yjsAwarenessInstance . getStates ( ) ;
689+ const states = presence . collabStates ( ) ;
695690 const localClientID = constants . mutableRefs . yjsAwarenessInstance . clientID ;
696691 const currentlyDisplayed = new Set ( constants . remoteUserIcons . keys ( ) ) ;
697692 const activeRemoteClientIDs = new Set ( ) ;
@@ -753,7 +748,7 @@ export function updateUserMenuBarIcons() {
753748export function updateSpriteUserIcons ( ) {
754749 if ( ! constants . mutableRefs . yjsAwarenessInstance || ! constants . mutableRefs . vm ) return ;
755750
756- const states = constants . mutableRefs . yjsAwarenessInstance . getStates ( ) ;
751+ const states = presence . collabStates ( ) ;
757752 const localClientID = constants . mutableRefs . yjsAwarenessInstance . clientID ;
758753 const spriteListElement = document . querySelector ( '[class*="sprite-selector_items-wrapper"]' ) ;
759754 const stageElement = document . querySelectorAll ( '[class*="stage-selector_stage-selector"]' ) [ 0 ] ;
@@ -885,7 +880,7 @@ export function updateSpriteUserIcons() {
885880export function updateTabUserIcons ( ) {
886881 if ( ! constants . mutableRefs . yjsAwarenessInstance || ! constants . mutableRefs . vm ) return ;
887882
888- const states = constants . mutableRefs . yjsAwarenessInstance . getStates ( ) ;
883+ const states = presence . collabStates ( ) ;
889884 const localClientID = constants . mutableRefs . yjsAwarenessInstance . clientID ;
890885 const tabElements = document . querySelectorAll ( constants . TAB_SELECTOR ) ;
891886 const localUserCurrentTargetId = constants . localUserInfo . currentTargetId ;
@@ -1194,3 +1189,66 @@ export function setupCSS() {
11941189export function getActiveRemoteClientIDs ( ) {
11951190 return new Set ( cursorElements . keys ( ) ) ;
11961191}
1192+
1193+ /*
1194+ * Telling somebody they are watching.
1195+ */
1196+ const VIEWER_BANNER_ID = 'collaboration-viewer-banner' ;
1197+
1198+ export function showViewerBanner ( ) {
1199+ if ( document . getElementById ( VIEWER_BANNER_ID ) ) return ;
1200+ const banner = document . createElement ( 'div' ) ;
1201+ banner . id = VIEWER_BANNER_ID ;
1202+ banner . textContent = 'You are watching this project. Ask the owner for edit access.' ;
1203+ banner . style . cssText = [
1204+ 'position:fixed' , 'left:50%' , 'transform:translateX(-50%)' , 'bottom:16px' ,
1205+ 'z-index:9999' , 'pointer-events:none' ,
1206+ 'background:rgba(35,39,50,0.94)' , 'color:#ffffff' ,
1207+ 'font-family:"Helvetica Neue", Helvetica, Arial, sans-serif' , 'font-size:13px' ,
1208+ 'padding:8px 16px' , 'border-radius:16px' , 'box-shadow:0 2px 8px rgba(0,0,0,.35)'
1209+ ] . join ( ';' ) ;
1210+ document . body . appendChild ( banner ) ;
1211+ }
1212+
1213+ export function hideViewerBanner ( ) {
1214+ document . getElementById ( VIEWER_BANNER_ID ) ?. remove ( ) ;
1215+ }
1216+
1217+ const VIEWER_STYLE_ID = 'collaboration-viewer-styles' ;
1218+
1219+ export function applyViewerWorkspace ( workspace ) {
1220+ if ( ! document . getElementById ( VIEWER_STYLE_ID ) ) {
1221+ const style = document . createElement ( 'style' ) ;
1222+ style . id = VIEWER_STYLE_ID ;
1223+
1224+ style . textContent = `
1225+ .blocklyBlockCanvas, .blocklyFlyout { pointer-events: none; }
1226+
1227+ [class*="sprite-selector_add-button"],
1228+ [class*="stage-selector_add-button"],
1229+ [class*="selector_new-buttons"],
1230+ [class*="sprite-selector-item_delete-button"] { display: none !important; }
1231+
1232+ [class*="sprite-info_sprite-info"] { pointer-events: none; opacity: .6; }
1233+
1234+ [class*="paint-editor_canvas-container"],
1235+ [class*="paint-editor_mode-selector"],
1236+ [class*="paint-editor_editor-container-top"] { pointer-events: none; }
1237+
1238+ [class*="sound-editor_effects"],
1239+ [class*="sound-editor_button-group"],
1240+ [class*="sound-editor_name-input"],
1241+ [class*="sound-editor_input-group"] { pointer-events: none; opacity: .6; }
1242+ ` ;
1243+ document . head . appendChild ( style ) ;
1244+ }
1245+ if ( ! workspace || ! workspace . options ) return ;
1246+ workspace . options . readOnly = true ;
1247+ const flyout = workspace . getFlyout && workspace . getFlyout ( ) ;
1248+ const flyoutWorkspace = flyout && flyout . getWorkspace && flyout . getWorkspace ( ) ;
1249+ if ( flyoutWorkspace && flyoutWorkspace . options ) flyoutWorkspace . options . readOnly = true ;
1250+ }
1251+
1252+ export function clearViewerWorkspace ( ) {
1253+ document . getElementById ( VIEWER_STYLE_ID ) ?. remove ( ) ;
1254+ }
0 commit comments