Skip to content

Commit 5a7088c

Browse files
committed
Feature setup
1 parent 1c691bb commit 5a7088c

File tree

4 files changed

+257
-7
lines changed

4 files changed

+257
-7
lines changed

injected/entry-points/integration.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function generateConfig() {
3333
'cookie',
3434
'webCompat',
3535
'apiManipulation',
36-
'duckPlayer',
36+
'duckPlayerNative',
3737
],
3838
},
3939
};
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width">
6+
<title>Duck Player - Player Overlay</title>
7+
<link rel="stylesheet" href="../../shared/style.css">
8+
<style>
9+
*, *:before, *:after {
10+
box-sizing: border-box;
11+
}
12+
body {
13+
max-width: 100%;
14+
margin-left: 0;
15+
margin-right: 0;
16+
}
17+
.controls {
18+
padding: 1em 0;
19+
}
20+
[data-layout=mobile] body {
21+
padding: 0;
22+
margin: 0;
23+
}
24+
.container {
25+
max-width: 800px;
26+
aspect-ratio: 16/9;
27+
background: blue;
28+
}
29+
[data-layout=mobile] .container {
30+
max-width: none;
31+
}
32+
#player {
33+
height: 100%;
34+
}
35+
.html5-video-player {
36+
position: relative;
37+
height: 100%;
38+
background: black;
39+
background-size: contain;
40+
}
41+
.tools {
42+
margin-bottom: 1rem;
43+
}
44+
video {
45+
display: block;
46+
height: 100%;
47+
width: 100%;
48+
}
49+
.thumbnails {
50+
display: grid;
51+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
52+
}
53+
.thumbnail {
54+
margin: 5px;
55+
background: lightblue;
56+
border: 1px solid black;
57+
aspect-ratio: 16/9;
58+
display: block;
59+
}
60+
61+
.thumbnail img, .short img {
62+
width: 100%;
63+
height: 100%;
64+
object-fit: cover;
65+
display: block;
66+
}
67+
</style>
68+
</head>
69+
<body>
70+
<script src="../../shared/utils.js"></script>
71+
<p><a href="../index.html">[Duck Player]</a></p>
72+
73+
<div class="controls">
74+
<div>
75+
<label for="locale-select">Choose locale:</label>
76+
<select id="locale-select"></select>
77+
</div>
78+
<div>
79+
<a href="?preview&wait-for-init-args&platform=ios">Preview iOS</a>
80+
<a href="?preview&wait-for-init-args&platform=macos">Preview macOS</a>
81+
</div>
82+
</div>
83+
84+
<script>
85+
const locales = ['bg', 'cs', 'da', 'de', 'el', 'en', 'es', 'et', 'fi', 'fr', 'hr', 'hu', 'it', 'lt', 'lv', 'nb', 'nl', 'pl', 'pt', 'ro', 'ru', 'sk', 'sl', 'sv', 'tr'];
86+
const localeSelect = document.getElementById('locale-select');
87+
88+
// Populate the select element with options
89+
locales.forEach(locale => {
90+
const option = document.createElement('option');
91+
option.value = locale;
92+
option.textContent = locale;
93+
localeSelect.appendChild(option);
94+
});
95+
96+
// Update the URL with the selected locale value
97+
localeSelect.addEventListener('change', (event) => {
98+
const selectedLocale = event.target.value;
99+
const url = new URL(window.location);
100+
url.searchParams.set('locale', selectedLocale);
101+
window.location.href = url
102+
});
103+
104+
// Reflect the selected value from the URL param on page load
105+
window.addEventListener('DOMContentLoaded', () => {
106+
const urlParams = new URLSearchParams(window.location.search);
107+
const localeFromUrl = urlParams.get('locale');
108+
if (localeFromUrl) {
109+
localeSelect.value = localeFromUrl;
110+
}
111+
});
112+
</script>
113+
114+
<div id="initial"></div>
115+
<div id="loaded"></div>
116+
117+
<main></main>
118+
<template id="inner-template">
119+
<div class="container">
120+
<div id="player">
121+
<div class="html5-video-player">
122+
<video width="800px" height="600px"></video>
123+
</div>
124+
</div>
125+
</div>
126+
</template>
127+
128+
<template id="related-template">
129+
<div class="related"><h2>Up next</h2>
130+
<div class="related-items">
131+
<div class="thumbnails">
132+
<a class="thumbnail" title="video 1" href="/watch?v=abc1"><img src="thumbnail-dark.jpg"></a>
133+
<a class="thumbnail" title="video 2" href="/watch?v=abc2"><img src="thumbnail-dark.jpg"></a>
134+
<a class="thumbnail" title="video 3" href="/watch?v=abc2"><img src="thumbnail-dark.jpg"></a>
135+
<a class="thumbnail" title="video 4" href="/watch?v=abc3"><img src="thumbnail-dark.jpg"></a>
136+
<a class="thumbnail" title="video 5" href="/watch?v=abc4"><img src="thumbnail-dark.jpg"></a>
137+
</div>
138+
</div>
139+
</div>
140+
</template>
141+
142+
<template id="playlist-template">
143+
<div class="playlist" id="playlist"><h2>Up next</h2>
144+
<div class="playlist-items">
145+
<div class="thumbnails">
146+
<a class="thumbnail" title="video 1" href="/watch?v=xyz1"><img src="thumbnail-dark.jpg"></a>
147+
<a class="thumbnail" title="video 2" href="/watch?v=xyz2"><img src="thumbnail-dark.jpg"></a>
148+
<a class="thumbnail" title="video 3" href="/watch?v=xyz2"><img src="thumbnail-dark.jpg"></a>
149+
<a class="thumbnail" title="video 4" href="/watch?v=xyz3"><img src="thumbnail-dark.jpg"></a>
150+
<a class="thumbnail" title="video 5" href="/watch?v=xyz4"><img src="thumbnail-dark.jpg"></a>
151+
</div>
152+
</div>
153+
</div>
154+
</template>
155+
<script>
156+
(async () => {
157+
settingsFiles = {
158+
default: '/duckplayer/config/overlays.json',
159+
drawer: '/duckplayer/config/overlays-drawer.json',
160+
}
161+
162+
if (!new URLSearchParams(location.search).has('preview')) {
163+
return;
164+
}
165+
const platformName = new URLSearchParams(window.location.search).get('platform') || 'macos';
166+
const locale = new URLSearchParams(window.location.search).get('locale') || 'en';
167+
const settingsId = new URLSearchParams(window.location.search).get('config') || 'default';
168+
169+
await import("/build/contentScope.js").catch(console.error)
170+
171+
const settingsFile = settingsFiles[settingsId] || settingsFiles.default;
172+
const overlays = await fetch(settingsFile).then(x => x.json())
173+
174+
document.dispatchEvent(new CustomEvent('content-scope-init-args', {
175+
detail: {
176+
debug: true,
177+
locale: locale,
178+
platform: {
179+
name: platformName,
180+
},
181+
site: {
182+
domain: location.hostname,
183+
isBroken: false,
184+
allowlisted: false,
185+
enabledFeatures: [
186+
'duckPlayerNative'
187+
]
188+
},
189+
featureSettings: {
190+
duckPlayer: overlays.features.duckPlayer.settings,
191+
}
192+
}
193+
}))
194+
})();
195+
</script>
196+
197+
<script type="module">
198+
const variant = new URLSearchParams(window.location.search).get('variant') || 'default';
199+
const main = document.querySelector('main');
200+
const html = (selector) => document.querySelector(selector).innerHTML
201+
202+
const knownVariants = {
203+
"default": () => {
204+
main.innerHTML += html('template[id="inner-template"]');
205+
main.innerHTML += html('template[id="related-template"]')
206+
main.innerHTML += html('template[id="playlist-template"]')
207+
},
208+
"mobile": () => {
209+
main.innerHTML += html('template[id="inner-template"]');
210+
document.documentElement.dataset.layout="mobile"
211+
},
212+
"incremental-dom": () => {
213+
main.innerHTML += `<div class="container"><div id="player"></div></div>`
214+
setTimeout(() => {
215+
const player = main.querySelector('#player');
216+
player.innerHTML = `
217+
<div class="html5-video-player">
218+
<video width="800px" height="600px"></video>
219+
</div>
220+
`
221+
main.innerHTML += html('template[id="related-template"]')
222+
main.innerHTML += html('template[id="playlist-template"]')
223+
}, 200);
224+
},
225+
}
226+
227+
if (variant in knownVariants) {
228+
console.log('executing page variant', variant)
229+
knownVariants[variant]();
230+
} else {
231+
console.warn('variant not found', variant)
232+
}
233+
234+
document.addEventListener('click', (e) => {
235+
if (e.target) {
236+
const a = e.target.closest('a');
237+
if (a && a.href.includes('/watch')) {
238+
e.preventDefault();
239+
const params = new URLSearchParams(a.search);
240+
const current = new URL(window.location.href);
241+
current.searchParams.set('v', params.get('v'));
242+
history.pushState('', '', current.toString());
243+
document.title = a.title;
244+
return;
245+
}
246+
}
247+
})
248+
249+
</script>
250+
</body>
251+
</html>

injected/src/features.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ const otherFeatures = /** @type {const} */ ([
3535
export const platformSupport = {
3636
apple: ['webCompat', 'duckPlayerNative', ...baseFeatures],
3737
'apple-isolated': [
38-
'duckPlayer',
3938
'duckPlayerNative',
4039
'brokerProtection',
4140
'performanceMetrics',

injected/src/features/duck-player-native.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ import { initDuckPlayerNative } from './duckplayer-native/duckplayer-native.js';
88
* @property {string} version - TODO: this is only here to test config. Replace with actual settings.
99
*/
1010

11-
export class DuckPlayerNative extends ContentFeature {
12-
init() {
13-
if (this.platform.name !== 'ios') return;
11+
export class DuckPlayerNativeFeature extends ContentFeature {
12+
init(args) {
13+
console.log('LOADING DUCK PLAYER NATIVE SCRIPTS', args);
1414

1515
/**
1616
* This feature never operates in a frame
1717
*/
18-
if (isBeingFramed()) return;
18+
// if (isBeingFramed()) return;
1919

2020
const comms = new DuckPlayerNativeMessages(this.messaging);
2121
initDuckPlayerNative(comms);
2222
}
2323
}
2424

25-
export default DuckPlayerNative;
25+
export default DuckPlayerNativeFeature;

0 commit comments

Comments
 (0)