-
Notifications
You must be signed in to change notification settings - Fork 397
fix(meetings): prevent stale whiteboard share event during content handoff #4958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -724,6 +724,7 @@ export default class Meeting extends StatelessWebexPlugin { | |
| allowMediaInLobby: boolean; | ||
| localShareInstanceId: string; | ||
| remoteShareInstanceId: string; | ||
| acceptedContentHandoffPreviousShare: any; | ||
| shareCAEventSentStatus: { | ||
| transmitStart: boolean; | ||
| transmitStop: boolean; | ||
|
|
@@ -1521,6 +1522,7 @@ export default class Meeting extends StatelessWebexPlugin { | |
| * @memberof Meeting | ||
| */ | ||
| this.remoteShareInstanceId = null; | ||
| this.acceptedContentHandoffPreviousShare = null; | ||
|
|
||
| /** | ||
| * Status used for ensuring we do not oversend metrics | ||
|
|
@@ -3206,20 +3208,50 @@ export default class Meeting extends StatelessWebexPlugin { | |
| newShareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE; | ||
| } | ||
| } | ||
| // or if content share is either released or null and whiteboard share is either released or null, no one is sharing | ||
| // Preserve active content sharing while another participant's content floor is only ACCEPTED. | ||
| // The final GRANTED update must still see the previous active share status so steal handling | ||
| // can unpublish local streams or update the remote presenter without emitting a stop event. | ||
| else if ( | ||
| ((previousContentShare && contentShare.disposition === FLOOR_ACTION.RELEASED) || | ||
| contentShare.disposition === null) && | ||
| ((previousWhiteboardShare && whiteboardShare.disposition === FLOOR_ACTION.RELEASED) || | ||
| whiteboardShare.disposition === null) | ||
| (this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE || | ||
| this.shareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE) && | ||
| previousContentShare?.disposition === FLOOR_ACTION.GRANTED && | ||
| contentShare.disposition === FLOOR_ACTION.ACCEPTED | ||
|
Comment on lines
+3217
to
+3218
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Locus sends more than one intermediate Useful? React with 👍 / 👎. |
||
| ) { | ||
| this.acceptedContentHandoffPreviousShare = previousContentShare; | ||
| newShareStatus = this.shareStatus; | ||
| } | ||
| // Otherwise, neither content nor whiteboard floor is GRANTED (covers | ||
| // RELEASED, null, and intermediate dispositions such as ACCEPTED), so no | ||
| // one is currently sharing. Active content shares are preserved above until | ||
| // another participant receives the final GRANTED floor update. | ||
| else { | ||
| newShareStatus = SHARE_STATUS.NO_SHARE; | ||
|
Comment on lines
+3227
to
3228
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a local content share is active and Locus sends an intermediate Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| LoggerProxy.logger.info( | ||
| `Meeting:index#setUpLocusInfoMediaInactiveListener --> this.shareStatus=${this.shareStatus} newShareStatus=${newShareStatus}` | ||
| ); | ||
|
|
||
| let mediaSharesUpdatePayload = payload; | ||
|
|
||
| if ( | ||
| this.acceptedContentHandoffPreviousShare && | ||
| contentShare.disposition === FLOOR_ACTION.GRANTED && | ||
| payload.previous?.content?.disposition === FLOOR_ACTION.ACCEPTED | ||
| ) { | ||
| mediaSharesUpdatePayload = { | ||
| ...payload, | ||
| previous: { | ||
| ...payload.previous, | ||
| content: this.acceptedContentHandoffPreviousShare, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| if (contentShare.disposition !== FLOOR_ACTION.ACCEPTED) { | ||
| this.acceptedContentHandoffPreviousShare = null; | ||
| } | ||
|
|
||
| if (newShareStatus !== this.shareStatus) { | ||
| const oldShareStatus = this.shareStatus; | ||
|
|
||
|
|
@@ -3393,8 +3425,11 @@ export default class Meeting extends StatelessWebexPlugin { | |
| break; | ||
| } | ||
|
|
||
| this.members.locusMediaSharesUpdate(payload); | ||
| } else if (newShareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE) { | ||
| this.members.locusMediaSharesUpdate(mediaSharesUpdatePayload); | ||
| } else if ( | ||
| newShareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE && | ||
| contentShare.disposition !== FLOOR_ACTION.ACCEPTED | ||
| ) { | ||
|
Comment on lines
+3429
to
+3432
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a content handoff goes through Useful? React with 👍 / 👎. |
||
| // if we got here, then some remote participant has stolen | ||
| // the presentation from another remote participant | ||
| this.remoteShareInstanceId = contentShare.shareInstanceId; | ||
|
|
@@ -3416,7 +3451,7 @@ export default class Meeting extends StatelessWebexPlugin { | |
| resourceType: contentShare.resourceType, | ||
| } | ||
| ); | ||
| this.members.locusMediaSharesUpdate(payload); | ||
| this.members.locusMediaSharesUpdate(mediaSharesUpdatePayload); | ||
| } else if (newShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) { | ||
| // if we got here, then some remote participant has stolen | ||
| // the presentation from another remote participant | ||
|
|
@@ -3442,7 +3477,7 @@ export default class Meeting extends StatelessWebexPlugin { | |
| meetingId: this.id, | ||
| }, | ||
| }); | ||
| this.members.locusMediaSharesUpdate(payload); | ||
| this.members.locusMediaSharesUpdate(mediaSharesUpdatePayload); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a webinar attendee or guest is viewing a whiteboard, the earlier whiteboard branch stores it as
REMOTE_SHARE_ACTIVE; if that whiteboard is then RELEASED while the next content floor is onlyACCEPTED, this new preservation branch treats the whiteboard-backed remote state as an active content share. In that context the listener skips the transition toNO_SHAREand the accepted-event path below is also suppressed, so the stale whiteboard/remote state remains until the final GRANTED update instead of stopping the released whiteboard as intended. Please gate this preservation on the previous/current content floor actually representing an active content share, not just on the sharedREMOTE_SHARE_ACTIVEstatus.Useful? React with 👍 / 👎.