move the ShareLink action to its own section at the bottom of the item menu
The button used to be cloned in next to "Copy Stream URL", or shoved at the top of the menu when there was none, which put it in the middle of Jellyfin's own command groups. Now there is a single injection path: append an actionsheetDivider plus the action at the end of the sheet's scroller, so it reads as its own section the way Jellyfin separates its groups. It also stopped appearing on menus for things that are not media. The old code resolved the item from the URL, so opening the "..." menu on a cast member inside a movie page showed ShareLink and would have shared the movie behind it. The item is now taken from the trigger that opened the menu (card, list row or the detail page's own button, all of which we can walk up from) and its type is checked against the server before anything is injected: movie, series, season, episode, nothing else. The API refuses everything else too, so a hand-rolled request cannot tag a person or a playlist either. Clicking the action now dismisses the action sheet instead of leaving it stacked under the dialog.
Cette révision appartient à :
@@ -12,6 +12,7 @@ using Jellyfin.Plugin.ShareLinks.Models;
|
||||
using Jellyfin.Plugin.ShareLinks.Services;
|
||||
using Jellyfin.Plugin.ShareLinks.Storage;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -202,10 +203,14 @@ public sealed class ShareLinksController : ControllerBase
|
||||
return NotFound(new { error = "Item not found." });
|
||||
}
|
||||
|
||||
if (item.IsFolder && item is not Series && item is not Season)
|
||||
if (!IsShareableItem(item))
|
||||
{
|
||||
_logger.LogWarning("ShareLinks: create rejected, item {ItemId} \"{ItemName}\" is a folder or library, not shareable media.", itemId, item.Name);
|
||||
return BadRequest(new { error = "Only a movie, episode, series or season can be shared, not a library or collection. Open the title's page and try again." });
|
||||
_logger.LogWarning(
|
||||
"ShareLinks: create rejected, item {ItemId} \"{ItemName}\" is a {ItemType}, which is not shareable media.",
|
||||
itemId,
|
||||
item.Name,
|
||||
item.GetType().Name);
|
||||
return BadRequest(new { error = "Only a movie, series, season or episode can be shared. Open the title's page and try again." });
|
||||
}
|
||||
|
||||
try
|
||||
@@ -412,6 +417,17 @@ setTimeout(function () { window.location.replace({{redirectUrlJson}}); }, 4000);
|
||||
?? User.Identity?.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only real video titles are shareable. Anything else - a person, studio,
|
||||
/// genre, library, collection, playlist, music track or book - would either
|
||||
/// give the guest nothing to play or pull unrelated items into the guest's tag
|
||||
/// policy, so the API refuses it even when a client asks for it.
|
||||
/// </summary>
|
||||
private static bool IsShareableItem(BaseItem item)
|
||||
{
|
||||
return item is Movie or Series or Season or Episode;
|
||||
}
|
||||
|
||||
private static bool IsExpired(ShareLinkRecord record)
|
||||
{
|
||||
return record.ExpiresAtUtc <= DateTimeOffset.UtcNow;
|
||||
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur