Skip to content

Commit 412f6b2

Browse files
committed
fix(player): fixes some crashes and warnings when using minimize presentation
Fixes some bugs mainly when seeking into/out minimized presentation.
1 parent 2a8656e commit 412f6b2

File tree

3 files changed

+66
-28
lines changed

3 files changed

+66
-28
lines changed

src/components/webcams/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ const buildOptions = (sources, tracks) => {
9090
};
9191

9292
const dispatchTimeUpdate = (time) => {
93-
const event = new CustomEvent(EVENTS.TIME_UPDATE, { detail: { time }});
93+
const event = new CustomEvent(EVENTS.TIME_UPDATE, { detail: { time } });
9494
document.dispatchEvent(event);
9595
};
9696

@@ -108,9 +108,10 @@ const Webcams = () => {
108108

109109
player.webcams = videojs(video, buildOptions(sources, tracks), () => {
110110
player.webcams.on('play', () => {
111+
if (interval.current) clearInterval(interval.current);
111112
const frequency = getFrequency();
112113
interval.current = setInterval(() => {
113-
if (player.webcams) {
114+
if (player.webcams && !player.webcams.isDisposed()) {
114115
const currentTime = player.webcams.currentTime();
115116
dispatchTimeUpdate(currentTime);
116117
}
@@ -140,6 +141,7 @@ const Webcams = () => {
140141

141142
useEffect(() => {
142143
return () => {
144+
if (interval.current) clearInterval(interval.current);
143145
if (player.webcams) {
144146
player.webcams.dispose();
145147
player.webcams = null;

src/utils/player.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,29 @@ const player = {
1818
return PLAYERS[ID.WEBCAMS];
1919
},
2020
set screenshare(value) {
21-
if (!PLAYERS[ID.SCREENSHARE]) PLAYERS[ID.SCREENSHARE] = value;
21+
PLAYERS[ID.SCREENSHARE] = value;
2222

23-
if (this.webcams) {
23+
if (this.synchronizer) {
24+
this.synchronizer.destroy();
25+
this.synchronizer = null;
26+
}
27+
28+
if (value && this.webcams) {
2429
this.synchronizer = new Synchronizer(this.webcams, this.screenshare);
2530
}
2631
},
2732
set synchronizer(value) {
28-
if (!SYNCHRONIZER) SYNCHRONIZER = value;
33+
SYNCHRONIZER = value;
2934
},
3035
set webcams(value) {
31-
if (!PLAYERS[ID.WEBCAMS]) PLAYERS[ID.WEBCAMS] = value;
36+
PLAYERS[ID.WEBCAMS] = value;
37+
38+
if (this.synchronizer) {
39+
this.synchronizer.destroy();
40+
this.synchronizer = null;
41+
}
3242

33-
if (this.screenshare) {
43+
if (value && this.screenshare) {
3444
this.synchronizer = new Synchronizer(this.webcams, this.screenshare);
3545
}
3646
},

src/utils/synchronizer.js

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export default class Synchronizer {
3939
constructor(primary, secondary) {
4040
this.primary = primary;
4141
this.secondary = secondary;
42+
this.listeners = [];
4243

4344
this.status = {
4445
primary: 'waiting',
@@ -50,66 +51,91 @@ export default class Synchronizer {
5051
this.init();
5152
}
5253

54+
_on(target, event, callback) {
55+
target.on(event, callback);
56+
this.listeners.push({ target, event, callback });
57+
}
58+
59+
destroy() {
60+
this.listeners.forEach(({ target, event, callback }) => {
61+
target.off(event, callback);
62+
});
63+
this.listeners = [];
64+
65+
if (this.visibilityHandler) {
66+
document.removeEventListener('visibilitychange', this.visibilityHandler);
67+
this.visibilityHandler = null;
68+
}
69+
}
70+
5371
init() {
5472
STATUSES.forEach(status => {
55-
this.primary.on(status, () => this.status.primary = status);
56-
this.secondary.on(status, () => this.status.secondary = status);
73+
this._on(this.primary, status, () => this.status.primary = status);
74+
this._on(this.secondary, status, () => this.status.secondary = status);
5775
});
5876

59-
this.primary.on('play', () => this.secondary.play());
60-
this.primary.on('pause', () => this.secondary.pause());
77+
this._on(this.primary, 'play', () => {
78+
if (!this.secondary?.isDisposed?.()) this.secondary?.play();
79+
});
80+
this._on(this.primary, 'pause', () => {
81+
if (!this.secondary?.isDisposed?.()) this.secondary?.pause();
82+
});
6183

62-
this.primary.on('seeking', () => {
84+
this._on(this.primary, 'seeking', () => {
85+
if (this.primary.isDisposed?.()) return;
6386
const currentTime = this.primary.currentTime();
64-
this.secondary.currentTime(currentTime);
87+
if (!this.secondary?.isDisposed?.()) this.secondary?.currentTime(currentTime);
6588
});
6689

67-
this.primary.on('ratechange', () => {
90+
this._on(this.primary, 'ratechange', () => {
91+
if (this.primary.isDisposed?.()) return;
6892
const playbackRate = this.primary.playbackRate();
69-
this.secondary.playbackRate(playbackRate);
93+
if (!this.secondary?.isDisposed?.()) this.secondary?.playbackRate(playbackRate);
7094
});
7195

72-
this.primary.on('waiting', () => {
96+
this._on(this.primary, 'waiting', () => {
7397
if (!this.synching && this.status.secondary === 'canplay') {
7498
this.synching = true;
75-
this.primary.pause();
99+
if (!this.primary.isDisposed?.()) this.primary.pause();
76100
}
77101
});
78102

79-
this.primary.on('canplay', () => {
103+
this._on(this.primary, 'canplay', () => {
80104
if (this.synching) {
81105
this.synching = false;
82-
this.primary.play();
106+
if (!this.primary.isDisposed?.()) this.primary.play();
83107
}
84108
});
85109

86-
this.secondary.on('waiting', () => {
110+
this._on(this.secondary, 'waiting', () => {
87111
if (!this.synching && this.status.primary === 'canplay') {
88112
this.synching = true;
89-
this.primary.pause();
113+
if (!this.primary.isDisposed?.()) this.primary.pause();
90114
}
91115
});
92116

93-
this.secondary.on('canplay', () => {
117+
this._on(this.secondary, 'canplay', () => {
94118
if (this.synching) {
95119
this.synching = false;
96-
this.primary.play();
120+
if (!this.primary.isDisposed?.()) this.primary.play();
97121
}
98122
});
99123

100124
// IMPORTANT: Blink holds the secondary media down while the document
101125
// page is not visible
102126
// Force medias to sync on visibility change and document is visible
103-
document.addEventListener('visibilitychange', () => {
127+
this.visibilityHandler = () => {
104128
if (document.visibilityState === 'visible') {
129+
if (this.primary.isDisposed?.()) return;
105130
const currentTime = this.primary.currentTime();
106-
this.secondary.currentTime(currentTime);
131+
if (!this.secondary?.isDisposed?.()) this.secondary?.currentTime(currentTime);
107132
}
108-
});
133+
};
134+
document.addEventListener('visibilitychange', this.visibilityHandler);
109135

110136
EVENTS.forEach(event => {
111-
this.primary.on(event, () => logger.debug(`primary ${event} ${this.status.primary}`));
112-
this.secondary.on(event, () => logger.debug(`secondary ${event} ${this.status.secondary}`));
137+
this._on(this.primary, event, () => logger.debug(`primary ${event} ${this.status.primary}`));
138+
this._on(this.secondary, event, () => logger.debug(`secondary ${event} ${this.status.secondary}`));
113139
});
114140
}
115141
}

0 commit comments

Comments
 (0)