diff --git a/Jellyfin.Plugin.ShareLinks/Api/ShareLinksController.cs b/Jellyfin.Plugin.ShareLinks/Api/ShareLinksController.cs
index 17b5aeb..1f475bb 100644
--- a/Jellyfin.Plugin.ShareLinks/Api/ShareLinksController.cs
+++ b/Jellyfin.Plugin.ShareLinks/Api/ShareLinksController.cs
@@ -91,6 +91,8 @@ public sealed class ShareLinkGuestStateDto
public DateTimeOffset? ExpiresAtUtc { get; set; }
public bool LockdownEnabled { get; set; }
+
+ public string? HiddenSelectors { get; set; }
}
/// ShareLinks API surface.
@@ -291,7 +293,8 @@ public sealed class ShareLinksController : ControllerBase
AllowedItemId = match.ItemId,
ShareId = match.Id,
ExpiresAtUtc = match.ExpiresAtUtc,
- LockdownEnabled = config.GuestModeLockdownEnabled
+ LockdownEnabled = config.GuestModeLockdownEnabled,
+ HiddenSelectors = config.GuestHiddenSelectors
});
}
}
@@ -299,7 +302,8 @@ public sealed class ShareLinksController : ControllerBase
return Ok(new ShareLinkGuestStateDto
{
IsGuest = false,
- LockdownEnabled = config.GuestModeLockdownEnabled
+ LockdownEnabled = config.GuestModeLockdownEnabled,
+ HiddenSelectors = config.GuestHiddenSelectors
});
}
diff --git a/Jellyfin.Plugin.ShareLinks/Configuration/PluginConfiguration.cs b/Jellyfin.Plugin.ShareLinks/Configuration/PluginConfiguration.cs
index dbc3799..d639ce5 100644
--- a/Jellyfin.Plugin.ShareLinks/Configuration/PluginConfiguration.cs
+++ b/Jellyfin.Plugin.ShareLinks/Configuration/PluginConfiguration.cs
@@ -41,4 +41,12 @@ public class PluginConfiguration : BasePluginConfiguration
/// Gets or sets a value indicating whether guest-mode lockdown is enabled.
public bool GuestModeLockdownEnabled { get; set; } = true;
+
+ ///
+ /// Gets or sets a comma-separated list of CSS selectors that are hidden from guest
+ /// sessions in the web client. Used to suppress other plugins' injected UI (search
+ /// bars, floating buttons) so a guest only sees the shared title. Defaults to the
+ /// AI Search plugin's elements.
+ ///
+ public string GuestHiddenSelectors { get; set; } = ".ais-fab,.ais-overlay,#ais-styles";
}
diff --git a/Jellyfin.Plugin.ShareLinks/Web/configPage.html b/Jellyfin.Plugin.ShareLinks/Web/configPage.html
index af35a35..8a0808b 100644
--- a/Jellyfin.Plugin.ShareLinks/Web/configPage.html
+++ b/Jellyfin.Plugin.ShareLinks/Web/configPage.html
@@ -123,6 +123,11 @@
+
+
@@ -207,6 +212,7 @@
page.querySelector('#MaxExpiryHours').value = cfg.MaxExpiryHours || 720;
page.querySelector('#PublicBaseUrlOverride').value = cfg.PublicBaseUrlOverride || '';
page.querySelector('#GuestUsernamePrefix').value = cfg.GuestUsernamePrefix || 'share-';
+ page.querySelector('#GuestHiddenSelectors').value = cfg.GuestHiddenSelectors != null ? cfg.GuestHiddenSelectors : '.ais-fab,.ais-overlay,#ais-styles';
page.querySelector('#AllowTranscoding').checked = cfg.AllowTranscoding !== false;
page.querySelector('#AllowRemuxing').checked = cfg.AllowRemuxing !== false;
page.querySelector('#CleanupIntervalMinutes').value = cfg.CleanupIntervalMinutes || 60;
@@ -387,6 +393,7 @@
cfg.MaxExpiryHours = parseInt(page.querySelector('#MaxExpiryHours').value, 10) || 720;
cfg.PublicBaseUrlOverride = page.querySelector('#PublicBaseUrlOverride').value.trim();
cfg.GuestUsernamePrefix = page.querySelector('#GuestUsernamePrefix').value.trim() || 'share-';
+ cfg.GuestHiddenSelectors = page.querySelector('#GuestHiddenSelectors').value;
cfg.AllowTranscoding = page.querySelector('#AllowTranscoding').checked;
cfg.AllowRemuxing = page.querySelector('#AllowRemuxing').checked;
cfg.CleanupIntervalMinutes = parseInt(page.querySelector('#CleanupIntervalMinutes').value, 10) || 60;
diff --git a/Jellyfin.Plugin.ShareLinks/Web/sharelinks.js b/Jellyfin.Plugin.ShareLinks/Web/sharelinks.js
index 12cb861..7dcc33f 100644
--- a/Jellyfin.Plugin.ShareLinks/Web/sharelinks.js
+++ b/Jellyfin.Plugin.ShareLinks/Web/sharelinks.js
@@ -2,7 +2,7 @@
var pluginId = '68540b76-ee74-436d-85ff-2abc884bbea6';
var copyLabel = 'Copy Stream URL';
var actionLabel = 'Create guest link';
- var clientVersion = '1.0.0-ui-modal-7';
+ var clientVersion = '1.0.0-ui-modal-8';
var allowedItemStorageKey = 'sharelinks.allowedItemId';
var guestClassName = 'sharelinks-guest';
var hiddenAttr = 'data-sharelinks-hidden';
@@ -172,6 +172,7 @@
}
ensureGuestStyle();
+ ensurePluginHideStyle(context.hiddenSelectors);
hideGuestControls();
// UX-only lockdown: the guest user's real access boundary is still the
@@ -202,7 +203,8 @@
allowedItemId: extractAllowedItemId(state) || sessionStorage.getItem(allowedItemStorageKey) || null,
username: username,
prefix: prefix,
- lockdownEnabled: lockdownEnabled
+ lockdownEnabled: lockdownEnabled,
+ hiddenSelectors: (state && (state.HiddenSelectors || state.hiddenSelectors)) || ''
};
}
@@ -227,10 +229,43 @@
var style = document.createElement('style');
style.id = 'ShareLinksGuestStyle';
style.textContent = 'body.' + guestClassName + ' [' + hiddenAttr + '="1"],'
- + ' body.' + guestClassName + ' .headerBackButton,'
+ ' body.' + guestClassName + ' .headerHomeButton,'
+ ' body.' + guestClassName + ' .mainDrawerButton,'
- + ' body.' + guestClassName + ' .headerSearchButton { display: none !important; }';
+ + ' body.' + guestClassName + ' .headerSearchButton,'
+ + ' body.' + guestClassName + ' [data-action="addtoplaylist"],'
+ + ' body.' + guestClassName + ' [data-action="addtocollection"] { display: none !important; }'
+ + ' body.' + guestClassName + ' .card,'
+ + ' body.' + guestClassName + ' #castCollapsible a,'
+ + ' body.' + guestClassName + ' .detailsGroupItem a,'
+ + ' body.' + guestClassName + ' .genresGroup a,'
+ + ' body.' + guestClassName + ' .studiosGroup a,'
+ + ' body.' + guestClassName + ' .mediaInfoItem a { pointer-events: none !important; cursor: default !important; }';
+ document.head.appendChild(style);
+ }
+
+ function ensurePluginHideStyle(selectors) {
+ var value = String(selectors || '').split(',').map(function (part) {
+ return part.trim();
+ }).filter(Boolean);
+ var existing = document.getElementById('ShareLinksPluginHideStyle');
+ if (value.length === 0) {
+ if (existing) {
+ existing.remove();
+ }
+ return;
+ }
+
+ var css = value.join(', ') + ' { display: none !important; }';
+ if (existing) {
+ if (existing.textContent !== css) {
+ existing.textContent = css;
+ }
+ return;
+ }
+
+ var style = document.createElement('style');
+ style.id = 'ShareLinksPluginHideStyle';
+ style.textContent = css;
document.head.appendChild(style);
}