Skip to content

Commit bbf1ef8

Browse files
committed
feat(view): add reusable VideoPlayer widget; intro video styles
Adds src/view/VideoPlayer.js — small AMD module exporting createPlayer that returns a jQuery-wrapped <video> with sensible defaults (controls on, muted, playsinline, preload=metadata) and overridable flags. Built to back AI-panel onboarding's new embedded-video surface and any future inline-video usage without each caller re-deriving the same defaults. Also extends Extn-AIChatPanel.less with .ai-intro-video-player so the embedded <video> matches the existing thumbnail's 16:9, 320px max, rounded-corner envelope. Layout stays identical regardless of which mode (thumbnail-link vs embedded) the config picks.
1 parent 30be56b commit bbf1ef8

2 files changed

Lines changed: 116 additions & 0 deletions

File tree

src/styles/Extn-AIChatPanel.less

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2822,6 +2822,24 @@
28222822
overflow-wrap: anywhere;
28232823
}
28242824

2825+
.ai-intro-video-player {
2826+
display: block;
2827+
width: 100%;
2828+
border: 1px solid rgba(255, 255, 255, 0.08);
2829+
border-radius: 8px;
2830+
overflow: hidden;
2831+
background: rgba(0, 0, 0, 0.25);
2832+
aspect-ratio: 16 / 9;
2833+
2834+
video {
2835+
display: block;
2836+
width: 100%;
2837+
height: 100%;
2838+
object-fit: cover;
2839+
background: rgba(0, 0, 0, 0.25);
2840+
}
2841+
}
2842+
28252843
.ai-intro-video-thumb {
28262844
position: relative;
28272845
display: block;

src/view/VideoPlayer.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* GNU AGPL-3.0 License
3+
*
4+
* Copyright (c) 2021 - present core.ai . All rights reserved.
5+
*
6+
* This program is free software: you can redistribute it and/or modify it under
7+
* the terms of the GNU Affero General Public License as published by the Free
8+
* Software Foundation, either version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the GNU Affero General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Affero General Public License along
15+
* with this program. If not, see https://opensource.org/licenses/AGPL-3.0.
16+
*
17+
*/
18+
19+
// @INCLUDE_IN_API_DOCS
20+
21+
/**
22+
* Tiny shared HTML5 `<video>` widget. Wraps a single `<video>` element in a
23+
* div so callers can drop a configured player into their UI without
24+
* re-deriving sensible defaults each time. Defaults (controls + muted +
25+
* playsinline + preload="metadata") are tuned for inline product videos —
26+
* the kind of "watch this short clip" surface where the user has not yet
27+
* signalled intent to play.
28+
*/
29+
define(function (require, exports, module) {
30+
31+
32+
/**
33+
* Build a `<video>` element wrapped in a div with sensible Phoenix
34+
* defaults. Returns the wrapper as a jQuery object; the caller appends
35+
* and disposes it.
36+
*
37+
* @param {Object} options
38+
* @param {string} options.src Video URL (required).
39+
* @param {string} [options.poster] Optional poster image URL.
40+
* @param {boolean} [options.controls=true] Show native player controls.
41+
* @param {boolean} [options.muted=true] Start muted.
42+
* @param {boolean} [options.autoplay=false] Autoplay on insert (browsers
43+
* only honour this when also muted).
44+
* @param {boolean} [options.loop=false]
45+
* @param {string} [options.preload="metadata"] One of "none", "metadata",
46+
* "auto". Use "auto" when you
47+
* want the bytes to fetch in
48+
* the background after the
49+
* poster paints.
50+
* @param {string} [options.className] Extra class on the wrapper.
51+
* @returns {jQuery} `<div class="phx-video-player ..."><video.../></div>`
52+
*/
53+
function createPlayer(options) {
54+
options = options || {};
55+
if (!options.src) {
56+
throw new Error("VideoPlayer.createPlayer: options.src is required");
57+
}
58+
const controls = options.controls !== false;
59+
const muted = options.muted !== false;
60+
const autoplay = options.autoplay === true;
61+
const loop = options.loop === true;
62+
const preload = options.preload || "metadata";
63+
64+
const wrapperClass = "phx-video-player" +
65+
(options.className ? " " + options.className : "");
66+
const $wrap = $('<div></div>').addClass(wrapperClass);
67+
const $video = $('<video playsinline></video>')
68+
.attr("preload", preload)
69+
.attr("src", options.src);
70+
71+
if (options.poster) {
72+
$video.attr("poster", options.poster);
73+
}
74+
if (controls) {
75+
$video.attr("controls", "");
76+
}
77+
// The DOM properties are what HTMLMediaElement actually reads at
78+
// load time; the matching attributes are set so server-side / dev
79+
// tooling that scrapes outerHTML still sees the configured state.
80+
if (muted) {
81+
$video.attr("muted", "");
82+
$video[0].muted = true;
83+
}
84+
if (autoplay) {
85+
$video.attr("autoplay", "");
86+
$video[0].autoplay = true;
87+
}
88+
if (loop) {
89+
$video.attr("loop", "");
90+
$video[0].loop = true;
91+
}
92+
93+
$wrap.append($video);
94+
return $wrap;
95+
}
96+
97+
exports.createPlayer = createPlayer;
98+
});

0 commit comments

Comments
 (0)