Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.0.0</Version>
<Version>9.0.1</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/components/BootstrapBlazor.Player/Player.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

@if (Mode == PlayerMode.Audio)
{
<audio id="@Id" playsinline controls crossorigin>
<audio id="@Id" playsinline controls crossorigin data-bb-event="@EventString">
</audio>
}
else {
<video id="@Id" playsinline controls crossorigin>
<video id="@Id" playsinline controls crossorigin data-bb-event="@EventString">
</video>
}
26 changes: 22 additions & 4 deletions src/components/BootstrapBlazor.Player/Player.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ public partial class Player
[EditorRequired]
public PlayerOptions? Options { get; set; }

private string? ClassString => CssBuilder.Default("bb-video-player")
.AddClassFromAttributes(AdditionalAttributes)
.Build();
/// <summary>
/// Gets or sets the client event callback. Default is null.
/// </summary>
[Parameter]
public Func<string, Task>? OnEvent { get; set; }

private string? EventString => OnEvent == null ? "true" : null;

/// <summary>
/// <inheritdoc/>
Expand All @@ -39,7 +43,7 @@ protected override async Task InvokeInitAsync()
{
Options.Language ??= CultureInfo.CurrentUICulture.Name;
}
await InvokeVoidAsync("init", Id, Interop, "", Options);
await InvokeVoidAsync("init", Id, Interop, nameof(TriggerEvent), Options);
}

/// <summary>
Expand All @@ -48,4 +52,18 @@ protected override async Task InvokeInitAsync()
/// <param name="option"></param>
/// <returns></returns>
public Task Reload(PlayerOptions option) => InvokeVoidAsync("reload", Id, option);

/// <summary>
/// Trigger <see cref="OnEvent"/> event callback. Triggered by JSInterop.
/// </summary>
/// <param name="eventName"></param>
/// <returns></returns>
[JSInvokable]
public async Task TriggerEvent(string eventName)
{
if (OnEvent != null)
{
await OnEvent(eventName);
}
}
}
106 changes: 61 additions & 45 deletions src/components/BootstrapBlazor.Player/Player.razor.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export async function init(id, invoke, method, options) {
...options
}
p.player = new Plyr(el, config);
handlerEvents(p);

if (source.sources.length === 0) {
return;
}
Expand All @@ -62,10 +64,69 @@ const initHls = (p, options) => {
setTimeout(() => hls.subtitleTrack = player.currentTrack, 50);
});
p.player = player;
handlerEvents(p);
});
}
}

export function reload(id, options) {
const p = Data.get(id);
if (p === null) {
return;
}

const { player, hls } = p;
const source = options.source.sources;
delete options.source;
if (hls) {
if (source.length > 0) {
const src = source[0].src;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)

Suggested change
const src = source[0].src;
const {src} = source[0];


ExplanationObject destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the Airbnb Javascript Style Guide

hls.loadSource(src);
}
}
else {
player.poster = source.poster ?? options.poster;
player.source = source;
}
}

export function setPoster(id, poster) {
const p = Data.get(id);
if (p) {
const { player } = p;
player.poster = poster;
}
}

export function dispose(id) {
const p = Data.get(id);
Data.remove(id);

if (p) {
const { player } = p;
if (player) {
player.destroy();
player = null;
Comment thread
ArgoZhang marked this conversation as resolved.
}
}
}

const handlerEventName = (name, p) => {
const { el, invoke, method, player } = p;
player.on(name, () => {
const fire = el.getAttribute('data-bb-event') === 'true';
if (fire) {
invoke.invokeMethodAsync(method, name);
}
});
}

const handlerEvents = p => {
Comment thread
ArgoZhang marked this conversation as resolved.
['ready', 'play', 'pause', 'ended', 'enterfullscreen', 'exitfullscreen', 'languagechange'].forEach(name => {
handlerEventName(name, p);
});
}

const setLang = (option) => {
option.i18n = {
restart: '重启',
Expand Down Expand Up @@ -112,48 +173,3 @@ const setLang = (option) => {
}
}
}

export function reload(id, options) {
const p = Data.get(id);
if (p === null) {
return;
}

const { player, hls } = p;
const source = options.source.sources;
delete options.source;
if (hls) {
if (source.length > 0) {
const src = source[0].src;
hls.loadSource(src);
}
}
else {
player.poster = source.poster ?? options.poster;
player.source = source;
}
}

export function setPoster(id, poster) {
execute(id, p => {
const { player } = p;
player.poster = poster;
});
}

const execute = (id, callback) => {
const p = Data.get(id);
if (p) {
callback(p);
}
}

export function dispose(id) {
const p = Data.get(id);
Data.remove(id);

execute(id, player => {
player.destroy();
player = null;
});
}