1
+ import {
2
+ SUBTITLE_TEXT_QUERY_SELECTOR ,
3
+ SUBTITLE_WRAPPER_QUERY_SELECTOR ,
4
+ TRANSLATED_SUBTITLE_TEXT_QUERY_SELECTOR ,
5
+ VIDEO_PLAYER_QUERY_SELECTOR
6
+ } from '@/constants/selectors' ;
1
7
import { settings$ } from '@/observables/settings' ;
8
+ import { settingsModalState$ } from '@/observables/settings-modal' ;
2
9
import { subtitles$ } from '@/observables/subtitles' ;
3
- import { ExtensionMessage , ExtensionMessageAction , ExtensionReply } from '@/types/ExtensionMessage' ;
10
+ import { ExtensionMessage , ExtensionMessageAction } from '@/types/ExtensionMessage' ;
4
11
import { TranslateMode } from '@/types/TranslateMode' ;
5
-
6
- const ACTIVATION_KEY = 't' ;
12
+ import { settingsModal } from './inject/settings-modal/main' ;
7
13
8
14
export default defineContentScript ( {
9
15
matches : [ '*://tv.nrk.no/*' , '*://clients5.google.com/*' ] ,
@@ -12,30 +18,34 @@ export default defineContentScript({
12
18
async main ( ) {
13
19
let mode : TranslateMode | undefined ;
14
20
let language : string | undefined ;
21
+ let activationKey : string | undefined ;
15
22
let activationKeyPressed = false ;
16
23
17
24
function shiftOriginalSubtitle ( ) {
18
- const subtitleContainer = document . querySelector ( 'tv-player-subtitles div' ) as HTMLDivElement ;
25
+ const subtitleContainer = document . querySelector ( SUBTITLE_WRAPPER_QUERY_SELECTOR ) as HTMLDivElement ;
26
+ if ( ! subtitleContainer ) return ;
19
27
subtitleContainer . style . width = '50%' ;
20
28
subtitleContainer . style . left = '0%' ;
21
29
}
22
30
23
31
function hideOriginalSubtitle ( ) {
24
- const subtitleContainer = document . querySelector ( 'tv-player-subtitles div' ) as HTMLDivElement ;
32
+ const subtitleContainer = document . querySelector ( SUBTITLE_WRAPPER_QUERY_SELECTOR ) as HTMLDivElement ;
33
+ if ( ! subtitleContainer ) return ;
25
34
subtitleContainer . style . opacity = '0' ;
26
35
}
27
36
28
37
function resetOriginalSubtitle ( ) {
29
- const subtitleContainer = document . querySelector ( 'tv-player-subtitles div' ) as HTMLDivElement ;
38
+ const subtitleContainer = document . querySelector ( SUBTITLE_WRAPPER_QUERY_SELECTOR ) as HTMLDivElement ;
39
+ if ( ! subtitleContainer ) return ;
30
40
subtitleContainer . style . width = '100%' ;
31
41
subtitleContainer . style . opacity = '1' ;
32
42
subtitleContainer . style . left = 'unset' ;
33
43
}
34
44
35
45
function appendTranslatedSubtitle ( content : string , width = '50%' ) {
36
- const subtitleContainer = document . querySelector ( 'tv-player-subtitles div' ) as HTMLDivElement ;
46
+ const subtitleContainer = document . querySelector ( SUBTITLE_WRAPPER_QUERY_SELECTOR ) as HTMLDivElement ;
37
47
const translateContainer = subtitleContainer . cloneNode ( true ) as HTMLDivElement ;
38
- const translateSubtitleText = translateContainer . querySelector ( '.tv-player-subtitle-text' ) as HTMLSpanElement ;
48
+ const translateSubtitleText = translateContainer . querySelector ( SUBTITLE_TEXT_QUERY_SELECTOR ) as HTMLSpanElement ;
39
49
if ( ! translateSubtitleText ) return ;
40
50
translateSubtitleText . innerText = content ;
41
51
translateContainer . style . left = 'unset' ;
@@ -47,39 +57,44 @@ export default defineContentScript({
47
57
}
48
58
49
59
function removeTranslatedSubtitle ( ) {
50
- const node = document . querySelector ( '*[data-translated="true"]' ) as HTMLDivElement ;
60
+ const node = document . querySelector ( TRANSLATED_SUBTITLE_TEXT_QUERY_SELECTOR ) as HTMLDivElement ;
61
+ if ( ! node ) return ;
51
62
node . remove ( ) ;
52
63
}
53
64
54
65
function hideTranslatedSubtitle ( ) {
55
- const node = document . querySelector ( '*[data-translated="true"]' ) as HTMLDivElement ;
66
+ const node = document . querySelector ( TRANSLATED_SUBTITLE_TEXT_QUERY_SELECTOR ) as HTMLDivElement ;
67
+ if ( ! node ) return ;
56
68
node . style . opacity = '0' ;
57
69
resetOriginalSubtitle ( ) ;
58
70
}
59
71
60
72
function showTranslatedSubtitle ( ) {
61
- const node = document . querySelector ( '*[data-translated="true"]' ) as HTMLDivElement ;
73
+ const node = document . querySelector ( TRANSLATED_SUBTITLE_TEXT_QUERY_SELECTOR ) as HTMLDivElement ;
74
+ if ( ! node ) return ;
62
75
node . style . opacity = '1' ;
63
76
shiftOriginalSubtitle ( ) ;
64
77
}
65
78
66
79
async function translateSubtitle ( subtitle : string [ ] ) : Promise < string > {
67
- const translation = ( await browser . runtime . sendMessage ( {
80
+ const translation = await browser . runtime . sendMessage ( {
68
81
action : ExtensionMessageAction . Translate ,
69
82
payload : {
70
83
source_lang : 'no' ,
71
84
target_lang : language ,
72
85
text : subtitle . join ( '\n' )
73
86
}
74
- } as ExtensionMessage ) ) as ExtensionReply < ExtensionMessageAction . Translate > ;
87
+ } as ExtensionMessage ) ;
75
88
if ( translation . error ) throw translation . error ;
76
89
return translation . response ;
77
90
}
78
91
79
92
document . addEventListener ( 'keydown' , ( e ) => {
80
- if ( e . key === ACTIVATION_KEY ) {
93
+ if ( e . key === activationKey ) {
94
+ e . preventDefault ( ) ;
95
+ e . stopPropagation ( ) ;
81
96
activationKeyPressed = true ;
82
- const video = document . querySelector ( 'tv-player video' ) as HTMLVideoElement ;
97
+ const video = document . querySelector ( VIDEO_PLAYER_QUERY_SELECTOR ) as HTMLVideoElement ;
83
98
switch ( mode ) {
84
99
case TranslateMode . KeyPress :
85
100
showTranslatedSubtitle ( ) ;
@@ -96,9 +111,11 @@ export default defineContentScript({
96
111
} ) ;
97
112
98
113
document . addEventListener ( 'keyup' , ( e ) => {
99
- if ( e . key === ACTIVATION_KEY ) {
114
+ if ( e . key === activationKey ) {
115
+ e . preventDefault ( ) ;
116
+ e . stopPropagation ( ) ;
100
117
activationKeyPressed = false ;
101
- const video = document . querySelector ( 'tv-player video' ) as HTMLVideoElement ;
118
+ const video = document . querySelector ( VIDEO_PLAYER_QUERY_SELECTOR ) as HTMLVideoElement ;
102
119
switch ( mode ) {
103
120
case TranslateMode . KeyPress :
104
121
hideTranslatedSubtitle ( ) ;
@@ -115,8 +132,16 @@ export default defineContentScript({
115
132
}
116
133
} ) ;
117
134
135
+ // Listen for settings changes
118
136
settings$ . language . forEach ( ( newLanguage ) => ( language = newLanguage ) ) ;
119
137
settings$ . mode . forEach ( ( newMode ) => ( mode = newMode ) ) ;
138
+ settings$ . activationKey . forEach ( ( newActivationKey ) => ( activationKey = newActivationKey ) ) ;
139
+
140
+ // Listen for player settings modal open state
141
+ settingsModalState$ . forEach ( ( isOpen ) => {
142
+ settingsModal [ isOpen ? 'mount' : 'unmount' ] ( ) ;
143
+ } ) ;
144
+
120
145
subtitles$ . forEach ( async ( subtitle ) => {
121
146
switch ( mode ) {
122
147
case TranslateMode . Enabled : {
0 commit comments