Skip to content

Commit 8db6a6a

Browse files
authored
fix: simplify & reduce flakeyness of subtitle observer (#14)
1 parent f74e0c1 commit 8db6a6a

File tree

2 files changed

+24
-37
lines changed

2 files changed

+24
-37
lines changed

constants/selectors.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export const SETTINGS_MODAL_QUERY_SELECTOR = 'player-settings-dialog';
2-
export const SUBTITLES_CONTAINER_QUERY_SELECTOR = 'tv-player-subtitles';
3-
export const SUBTITLE_WRAPPER_QUERY_SELECTOR = 'tv-player-subtitles div';
2+
export const SUBTITLE_WRAPPER_QUERY_SELECTOR = 'tv-player-subtitles > div';
43
export const SUBTITLE_TEXT_QUERY_SELECTOR = '.tv-player-subtitle-text';
54
export const TRANSLATED_SUBTITLE_TEXT_QUERY_SELECTOR = '*[data-translated="true"]';
65
export const VIDEO_PLAYER_QUERY_SELECTOR = 'tv-player video';

observables/subtitles.ts

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,36 @@
1-
import { SUBTITLES_CONTAINER_QUERY_SELECTOR } from '@/constants/selectors';
2-
import { Observable } from 'rxjs';
1+
import { SUBTITLE_WRAPPER_QUERY_SELECTOR } from '@/constants/selectors';
2+
import { distinctUntilChanged, map, Observable } from 'rxjs';
33

4-
export const subtitles$ = new Observable<string[]>((subscriber) => {
4+
export const subtitles$ = new Observable<string>((subscriber) => {
55
const subtitlesObserver = new MutationObserver((mutations) => {
66
mutations.forEach((mutation) => {
7-
Array.from(mutation.addedNodes ?? []).forEach((node) => {
8-
node instanceof HTMLElement &&
9-
node.getAttribute('data-translated') !== 'true' &&
10-
subscriber.next(
11-
node.innerText
12-
.split('\n')
13-
.map((line) => line.trim())
14-
.filter((line) => !!line)
15-
);
7+
mutation.addedNodes.forEach((node) => {
8+
// Ensure that the added node is a subtitle and has not already been translated
9+
if (!(node instanceof HTMLElement)) return;
10+
if (!node.matches(SUBTITLE_WRAPPER_QUERY_SELECTOR)) return;
11+
if (node.matches('[data-translated]')) return;
12+
subscriber.next(node.innerText);
1613
});
1714
});
1815
});
1916

20-
const subtitleParentObserver = new MutationObserver((mutations) => {
21-
mutations.forEach((mutation) => {
22-
const subtitlesContainer = Array.from(mutation.addedNodes ?? []).find(
23-
(node) => node instanceof HTMLElement && node.matches(SUBTITLES_CONTAINER_QUERY_SELECTOR)
24-
);
25-
if (subtitlesContainer) {
26-
subtitlesObserver.observe(subtitlesContainer, {
27-
childList: true,
28-
subtree: true,
29-
attributes: false,
30-
characterData: false
31-
});
32-
subtitleParentObserver.disconnect();
33-
}
34-
});
35-
});
36-
37-
subtitleParentObserver.observe(document, {
17+
subtitlesObserver.observe(document, {
3818
childList: true,
3919
subtree: true,
4020
attributes: false,
4121
characterData: false
4222
});
4323

44-
return () => {
45-
subtitlesObserver.disconnect();
46-
subtitleParentObserver.disconnect();
47-
};
48-
});
24+
return () => subtitlesObserver.disconnect();
25+
})
26+
// Don't fire duplicate subtitle events
27+
.pipe(distinctUntilChanged())
28+
// Transform the subtitle into trimmed lines
29+
.pipe(
30+
map((text) =>
31+
text
32+
.split('\n')
33+
.map((line) => line.trim())
34+
.filter((line) => !!line)
35+
)
36+
);

0 commit comments

Comments
 (0)