Skip to content

Commit 61db7b6

Browse files
committed
feat(airplay-button): introduces a new airplay button component
Resolves #68 by adding a new AirPlayButton component. The implementation is based on the AirPlay support from the legacy Letterbox player, with one key difference: The button now handle the "not-available" state of the `webkitplaybacktargetavailabilitychanged` event. This component is only functional in Safari browsers, as it relies on the non-standard `webkit` API.
1 parent a924f25 commit 61db7b6

24 files changed

+818
-3
lines changed

assets/extensions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,9 @@
3434
{
3535
"name": "chapters-bar",
3636
"description": "Displays a scrollable list of video chapters, allowing users to easily navigate through the content."
37+
},
38+
{
39+
"name": "airplay-button",
40+
"description": "Adds an AirPlay button when AirPlay is available, and opens the system picker on click."
3741
}
3842
]

package-lock.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414
"homepage": "https://plugins.pillarbox.ch",
1515
"type": "module",
1616
"workspaces": [
17-
"packages/*",
18-
"themes/*"
17+
"packages/web-suite-utils",
18+
"packages/card",
19+
"packages/*"
1920
],
2021
"scripts": {
2122
"create": "plop --plopfile scripts/create.js",
2223
"eslint": "eslint {packages/**/{src,test}/**/*.{js,jsx},scripts/*.{js,jsx}}",
23-
"github:page": "npm run github:page --ws && vite build && node scripts/prepare-deployment.js",
24+
"github:page": "npm run github:page --ws --if-present && vite build && node scripts/prepare-deployment.js",
2425
"start": " vite --host --port 4200 --open",
2526
"outdated": "npm outdated",
2627
"prepare": "husky",

packages/airplay-button/.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "../../babel.config.json"
3+
}

packages/airplay-button/.releaserc

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
{
2+
"branches": ["main"],
3+
"extends": "semantic-release-monorepo",
4+
"plugins": [
5+
"@semantic-release/commit-analyzer",
6+
[
7+
"@semantic-release/release-notes-generator",
8+
{
9+
"preset": "conventionalcommits",
10+
"parserOpts": {
11+
"noteKeywords": [
12+
"BREAKING CHANGE",
13+
"BREAKING CHANGES",
14+
"BREAKING"
15+
]
16+
},
17+
"presetConfig": {
18+
"types": [
19+
{
20+
"type": "breaking",
21+
"section": "Breaking Changes ❗",
22+
"hidden": false
23+
},
24+
{
25+
"type": "feat",
26+
"section": "New Features 🚀",
27+
"hidden": false
28+
},
29+
{
30+
"type": "fix",
31+
"section": "Enhancements and Bug Fixes 🐛",
32+
"hidden": false
33+
},
34+
{
35+
"type": "docs",
36+
"section": "Docs 📖",
37+
"hidden": false
38+
},
39+
{
40+
"type": "style",
41+
"section": "Styles 🎨",
42+
"hidden": false
43+
},
44+
{
45+
"type": "refactor",
46+
"section": "Refactor 🔩",
47+
"hidden": false
48+
},
49+
{
50+
"type": "perf",
51+
"section": "Performances ⚡️",
52+
"hidden": false
53+
},
54+
{
55+
"type": "test",
56+
"section": "Tests ✅",
57+
"hidden": false
58+
},
59+
{
60+
"type": "ci",
61+
"section": "CI 🔁",
62+
"hidden": false
63+
},
64+
{
65+
"type": "chore",
66+
"section": "Chore 🧹",
67+
"hidden": false
68+
}
69+
]
70+
},
71+
"writerOpts": {
72+
"groupBy": "type",
73+
"commitGroupsSort": [
74+
"breaking",
75+
"feat",
76+
"fix"
77+
]
78+
}
79+
}
80+
],
81+
[
82+
"@semantic-release/changelog",
83+
{
84+
"changelogFile": "CHANGELOG.md"
85+
}
86+
],
87+
"@semantic-release/npm",
88+
[
89+
"@semantic-release/git",
90+
{
91+
"assets": [
92+
"package.json",
93+
"package-lock.json",
94+
"CHANGELOG.md"
95+
],
96+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
97+
}
98+
],
99+
[
100+
"@semantic-release/github",
101+
{
102+
"assets": [
103+
{
104+
"path": "dist/**/*"
105+
}
106+
]
107+
}
108+
]
109+
]
110+
}
111+

packages/airplay-button/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 SRG SSR
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/airplay-button/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Pillarbox Web: Airplay-Button
2+
3+
A Video.js component that adds native Apple AirPlay support. Shows a configurable AirPlay icon in
4+
the control bar when AirPlay is available, and opens the system picker on click.
5+
6+
## Requirements
7+
8+
To use this button, you need the following installed on your system:
9+
10+
- Node.js
11+
12+
## Quick Start
13+
14+
To get started with this button, install it through the following command:
15+
16+
```bash
17+
npm install --save video.js @srgssr/airplay-button
18+
```
19+
20+
Once the player is installed you can activate the button as follows:
21+
22+
```javascript
23+
import videojs from 'video.js';
24+
import '@srgssr/airplay-button';
25+
// (Optional) Import the provided SVG
26+
import airplayIcon from '@srgssr/airplay-button/assets/airplay.svg?raw';
27+
28+
const player = videojs('my-player');
29+
const controlBar = player.controlBar;
30+
31+
// Add the AirPlay button to the control bar, placing it second to last
32+
controlBar.addChild('AirplayButton', { icon: airplayIcon }, controlBar.children().length - 1);
33+
```
34+
35+
To apply the default styling, add the following line to your CSS file:
36+
37+
```css
38+
@import "@srgssr/airplay-button/dist/airplay-button.min.css";
39+
```
40+
41+
## API Documentation
42+
43+
### Options
44+
45+
When initializing the `AirplayButton` component, you can pass an `options` object to customize its
46+
behavior:
47+
48+
| Option | Type | Default | Description |
49+
|--------|-------------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------------------|
50+
| `icon` | `SVGElement \| string \| URL` | `undefined` | An SVG icon to display inside the button. Can be an SVGElement, a raw SVG string, or a URL (string or URL object). Throws if invalid. |
51+
52+
### Icon Integration
53+
54+
The `AirplayButton` supports multiple strategies for integrating a custom icon, depending on your
55+
project setup and preferences:
56+
57+
#### 1. Using SVG Icon Class (with experimental SVG icons)
58+
59+
If your project uses Video.js’s [experimental SVG icon support][experimental-svg], the button
60+
automatically includes the `vjs-icon-airplay` class, simply register an icon named `airplay` in your
61+
SVG icon set.
62+
63+
#### 2. Using a Custom Font Icon
64+
65+
If your project uses an icon font (such as Font Awesome or a custom font), you can style the Airplay
66+
button via CSS:
67+
68+
```css
69+
.vjs-airplay-button .vjs-icon-placeholder::before {
70+
content: '\f123'; /* Your font icon’s Unicode */
71+
font-family: 'YourCustomFont';
72+
}
73+
```
74+
75+
#### 3. Providing an Icon via Options
76+
77+
You can also pass a custom icon directly using the `icon` option. This works regardless of whether
78+
experimental SVG support is enabled. Accepted formats are:
79+
80+
* An `SVGElement` instance.
81+
* A raw inline SVG string.
82+
* A URL pointing to an external SVG file (as a string or `URL` object)
83+
84+
> [!TIP]
85+
> An AirPlay icon is included with this package under the assets/ directory and can be used
86+
> directly.
87+
88+
Example (using the built-in icon):
89+
90+
```js
91+
import airplayIcon from '@srgssr/assets/airplay.svg?raw';
92+
93+
player.controlBar.addChild('AirplayButton', { icon: airplayIcon });
94+
```
95+
96+
## Contributing
97+
98+
For detailed contribution guidelines, refer to our [Contributing guide][contributing-guide].
99+
Please adhere to the specified guidelines.
100+
101+
### Setting up a development server
102+
103+
Start the development server:
104+
105+
```bash
106+
npm run start
107+
```
108+
109+
This will start the server on `http://localhost:4200`. Open this URL in your browser to view the
110+
demo page.
111+
112+
The video player (`player`) and the Pillarbox library (`pillarbox`) are exposed on the `window`
113+
object, making it easy to access and manipulate from the browser's developer console for debugging.
114+
115+
#### Available URL parameters
116+
117+
The demo page supports several URL parameters that modify the behavior of the video player:
118+
119+
- `debug`: Set this to enable debugging mode.
120+
- `ilHost`: Specifies the host for the data provider.
121+
- `language`: Sets the language for the player interface.
122+
- `urn`: Specifies the URN of the video to load. Default is `urn:rts:video:14683290`.
123+
124+
You can combine parameters in the URL like so:
125+
126+
```plaintext
127+
http://localhost:4200/?language=fr&urn=urn:rts:video:14318206
128+
```
129+
130+
## Licensing
131+
132+
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more
133+
details.
134+
135+
[contributing-guide]: https://github.com/SRGSSR/pillarbox-web-suite/blob/main/docs/README.md#contributing
136+
137+
[experimental-svg]: https://videojs.com/guides/options/#experimentalsvgicons
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)