Hermes Agent commited on
Commit
23463b4
·
1 Parent(s): bfa9bd9

feat: modern streaming upgrades - 16:9 landscape continue watching rails, hide my media row, frosted glass catalog toolbar

Browse files
Files changed (2) hide show
  1. apex/ui/abyss.css +195 -32
  2. apex/ui/spotlight-loader.js +30 -14
apex/ui/abyss.css CHANGED
@@ -4209,53 +4209,56 @@ button[data-action="search"] {
4209
  margin-right: 14px !important;
4210
  }
4211
 
4212
- /* 1. Continue Watching & Next Up: Strict Uniform 2:3 Vertical Rectangular Posters Across ALL Devices */
4213
  .resumeSection .card,
4214
  .nextUpSection .card,
4215
  div[data-category="resume"] .card,
4216
- div[data-category="nextup"] .card,
4217
- .card[data-type="Episode"]:is(.resumeSection *, div[data-category="resume"] *, #indexPage *),
4218
- .backdropCard:is(.resumeSection *, div[data-category="resume"] *, #indexPage *) {
4219
- width: 140px !important;
4220
- max-width: 140px !important;
4221
- min-width: 140px !important;
4222
- flex: 0 0 140px !important;
 
 
 
 
 
 
 
 
 
 
 
4223
  }
4224
 
4225
- /* Force 2:3 vertical aspect-ratio on cardPadder (150% padding-bottom overrides Jellyfin 56.25% 16:9) */
4226
  .resumeSection .cardPadder,
4227
  .nextUpSection .cardPadder,
4228
  div[data-category="resume"] .cardPadder,
4229
  div[data-category="nextup"] .cardPadder,
4230
- #indexPage .itemsContainer-slider .cardPadder,
4231
- .cardPadder:is(.resumeSection *, div[data-category="resume"] *, #indexPage *),
4232
- .cardPadder-backdrop:is(.resumeSection *, div[data-category="resume"] *, #indexPage *),
4233
- .cardPadder-overflowBackdrop:is(.resumeSection *, div[data-category="resume"] *, #indexPage *),
4234
- .cardPadder-smallBackdrop:is(.resumeSection *, div[data-category="resume"] *, #indexPage *) {
4235
- padding-bottom: 150% !important;
4236
- aspect-ratio: 2 / 3 !important;
4237
  height: 0 !important;
4238
  }
4239
 
4240
  .resumeSection .cardScalable,
4241
  .nextUpSection .cardScalable,
4242
  div[data-category="resume"] .cardScalable,
4243
- div[data-category="nextup"] .cardScalable,
4244
- .resumeSection .card[data-type="Episode"] .cardScalable,
4245
- .nextUpSection .card[data-type="Episode"] .cardScalable,
4246
- div[data-category="resume"] .card[data-type="Episode"] .cardScalable,
4247
- div[data-category="nextup"] .card[data-type="Episode"] .cardScalable,
4248
- .cardScalable:is(.resumeSection *, div[data-category="resume"] *, #indexPage *) {
4249
- aspect-ratio: 2 / 3 !important;
4250
  border-radius: 12px !important;
4251
  overflow: hidden !important;
 
 
4252
  }
4253
 
4254
  .resumeSection .cardImageContainer img,
4255
  .nextUpSection .cardImageContainer img,
4256
  div[data-category="resume"] .cardImageContainer img,
4257
- div[data-category="nextup"] .cardImageContainer img,
4258
- #indexPage .itemsContainer-slider .cardImageContainer img {
4259
  object-fit: cover !important;
4260
  width: 100% !important;
4261
  height: 100% !important;
@@ -4264,17 +4267,43 @@ div[data-category="nextup"] .cardImageContainer img,
4264
  left: 0 !important;
4265
  }
4266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4267
  @media (max-width: 600px) {
4268
  .resumeSection .card,
4269
  .nextUpSection .card,
4270
  div[data-category="resume"] .card,
4271
- div[data-category="nextup"] .card,
4272
- .card[data-type="Episode"]:is(.resumeSection *, div[data-category="resume"] *, #indexPage *),
4273
- .backdropCard:is(.resumeSection *, div[data-category="resume"] *, #indexPage *) {
4274
- width: 120px !important;
4275
- max-width: 120px !important;
4276
- min-width: 120px !important;
4277
- flex: 0 0 120px !important;
4278
  }
4279
  }
4280
 
@@ -5719,3 +5748,137 @@ html.abyss-spotlight-visible .homeSectionsContainer {
5719
  position: relative;
5720
  z-index: 1;
5721
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4209
  margin-right: 14px !important;
4210
  }
4211
 
4212
+ /* 1. Continue Watching & Next Up: True 16:9 Widescreen Landscape Rails (Android TV & Modern Streaming) */
4213
  .resumeSection .card,
4214
  .nextUpSection .card,
4215
  div[data-category="resume"] .card,
4216
+ div[data-category="nextup"] .card {
4217
+ width: 230px !important;
4218
+ max-width: 230px !important;
4219
+ min-width: 230px !important;
4220
+ flex: 0 0 230px !important;
4221
+ scroll-snap-align: start !important;
4222
+ }
4223
+
4224
+ @media (min-width: 800px) {
4225
+ .resumeSection .card,
4226
+ .nextUpSection .card,
4227
+ div[data-category="resume"] .card,
4228
+ div[data-category="nextup"] .card {
4229
+ width: 275px !important;
4230
+ max-width: 275px !important;
4231
+ min-width: 275px !important;
4232
+ flex: 0 0 275px !important;
4233
+ }
4234
  }
4235
 
 
4236
  .resumeSection .cardPadder,
4237
  .nextUpSection .cardPadder,
4238
  div[data-category="resume"] .cardPadder,
4239
  div[data-category="nextup"] .cardPadder,
4240
+ .cardPadder-backdrop,
4241
+ .cardPadder-overflowBackdrop {
4242
+ padding-bottom: 56.25% !important;
4243
+ aspect-ratio: 16 / 9 !important;
 
 
 
4244
  height: 0 !important;
4245
  }
4246
 
4247
  .resumeSection .cardScalable,
4248
  .nextUpSection .cardScalable,
4249
  div[data-category="resume"] .cardScalable,
4250
+ div[data-category="nextup"] .cardScalable {
4251
+ aspect-ratio: 16 / 9 !important;
 
 
 
 
 
4252
  border-radius: 12px !important;
4253
  overflow: hidden !important;
4254
+ position: relative !important;
4255
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6) !important;
4256
  }
4257
 
4258
  .resumeSection .cardImageContainer img,
4259
  .nextUpSection .cardImageContainer img,
4260
  div[data-category="resume"] .cardImageContainer img,
4261
+ div[data-category="nextup"] .cardImageContainer img {
 
4262
  object-fit: cover !important;
4263
  width: 100% !important;
4264
  height: 100% !important;
 
4267
  left: 0 !important;
4268
  }
4269
 
4270
+ /* Streaming Watch Progress Bar (Netflix / Android TV Red Glow) */
4271
+ .resumeSection .itemProgressBar,
4272
+ .nextUpSection .itemProgressBar,
4273
+ div[data-category="resume"] .itemProgressBar,
4274
+ div[data-category="nextup"] .itemProgressBar,
4275
+ #indexPage .itemProgressBar {
4276
+ position: absolute !important;
4277
+ bottom: 0 !important;
4278
+ left: 0 !important;
4279
+ right: 0 !important;
4280
+ height: 4px !important;
4281
+ background: rgba(255, 255, 255, 0.22) !important;
4282
+ border-radius: 0 0 12px 12px !important;
4283
+ overflow: hidden !important;
4284
+ z-index: 5 !important;
4285
+ }
4286
+
4287
+ .resumeSection .itemProgressBarForeground,
4288
+ .nextUpSection .itemProgressBarForeground,
4289
+ div[data-category="resume"] .itemProgressBarForeground,
4290
+ div[data-category="nextup"] .itemProgressBarForeground,
4291
+ #indexPage .itemProgressBarForeground {
4292
+ background: linear-gradient(90deg, #E50914 0%, #FF2E4D 100%) !important;
4293
+ border-radius: 0 0 12px 12px !important;
4294
+ height: 100% !important;
4295
+ box-shadow: 0 0 8px rgba(229, 9, 20, 0.6) !important;
4296
+ }
4297
+
4298
  @media (max-width: 600px) {
4299
  .resumeSection .card,
4300
  .nextUpSection .card,
4301
  div[data-category="resume"] .card,
4302
+ div[data-category="nextup"] .card {
4303
+ width: 215px !important;
4304
+ max-width: 215px !important;
4305
+ min-width: 215px !important;
4306
+ flex: 0 0 215px !important;
 
 
4307
  }
4308
  }
4309
 
 
5748
  position: relative;
5749
  z-index: 1;
5750
  }
5751
+
5752
+ /* ========================================================
5753
+ MODERN STREAMING UPGRADES: PURE ANDROID TV & STREAMING APP
5754
+ ======================================================== */
5755
+
5756
+ /* 1. Hide redundant "My Media" library folders row from Home feed */
5757
+ #indexPage .verticalSection:has([data-type="CollectionFolder"]),
5758
+ #indexPage .verticalSection:has([data-type="UserView"]),
5759
+ #indexPage .verticalSection:has(.card[data-type="CollectionFolder"]),
5760
+ #indexPage .verticalSection:has(.card[data-type="UserView"]),
5761
+ #indexPage [data-category="views"],
5762
+ #indexPage .section0 {
5763
+ display: none !important;
5764
+ visibility: hidden !important;
5765
+ height: 0 !important;
5766
+ margin: 0 !important;
5767
+ padding: 0 !important;
5768
+ overflow: hidden !important;
5769
+ pointer-events: none !important;
5770
+ }
5771
+
5772
+ /* 2. Modernized Catalog Action Toolbar (Replaces stark white buttons with frosted glass) */
5773
+ .viewSettings,
5774
+ .libraryViewNav {
5775
+ display: flex !important;
5776
+ align-items: center !important;
5777
+ justify-content: flex-end !important;
5778
+ gap: 8px !important;
5779
+ padding: 8px 14px !important;
5780
+ margin: 0 !important;
5781
+ }
5782
+
5783
+ /* Suppress nonsensical Play All & Shuffle All on Movie and TV series catalog grids */
5784
+ .libraryPage :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"], button[data-action="play"], button[data-action="shuffle"]),
5785
+ #moviesPage :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"]),
5786
+ #tvShowsPage :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"]),
5787
+ .viewSettings :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"], button[data-action="play"], button[data-action="shuffle"]) {
5788
+ display: none !important;
5789
+ visibility: hidden !important;
5790
+ width: 0 !important;
5791
+ height: 0 !important;
5792
+ padding: 0 !important;
5793
+ margin: 0 !important;
5794
+ pointer-events: none !important;
5795
+ overflow: hidden !important;
5796
+ }
5797
+
5798
+ /* Frosted glass icon buttons for filters, sort, view toggles, and paging */
5799
+ .viewSettings button,
5800
+ .viewSettings .paper-icon-button-light,
5801
+ .libraryViewNav button,
5802
+ .listPaging button {
5803
+ background: rgba(255, 255, 255, 0.08) !important;
5804
+ backdrop-filter: blur(14px) !important;
5805
+ -webkit-backdrop-filter: blur(14px) !important;
5806
+ border: 1px solid rgba(255, 255, 255, 0.12) !important;
5807
+ color: rgba(255, 255, 255, 0.85) !important;
5808
+ border-radius: 9999px !important;
5809
+ transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important;
5810
+ }
5811
+
5812
+ .viewSettings button:hover,
5813
+ .viewSettings button:focus-visible,
5814
+ .libraryViewNav button:hover,
5815
+ .libraryViewNav button:focus-visible {
5816
+ background: rgba(255, 255, 255, 0.22) !important;
5817
+ border-color: rgba(255, 255, 255, 0.35) !important;
5818
+ color: #FFFFFF !important;
5819
+ transform: scale(1.06) !important;
5820
+ }
5821
+
5822
+ /* 3. Android TV Card Bento Focus & Hover Elevation */
5823
+ .itemsContainer .card:focus-visible,
5824
+ .itemsContainer .card:hover,
5825
+ .itemsContainer-slider .card:focus-visible,
5826
+ .itemsContainer-slider .card:hover {
5827
+ transform: scale(1.04) translateY(-2px) !important;
5828
+ z-index: 10 !important;
5829
+ transition: transform 0.24s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.24s cubic-bezier(0.16, 1, 0.3, 1) !important;
5830
+ }
5831
+
5832
+ .itemsContainer .card:focus-visible .cardScalable,
5833
+ .itemsContainer .card:hover .cardScalable,
5834
+ .itemsContainer-slider .card:focus-visible .cardScalable,
5835
+ .itemsContainer-slider .card:hover .cardScalable {
5836
+ box-shadow: 0 12px 28px rgba(0, 0, 0, 0.85), 0 0 0 1.5px rgba(255, 255, 255, 0.35) !important;
5837
+ }
5838
+
5839
+ /* 4. Streaming Typography: Multi-line clean title clamp instead of abrupt cutoffs */
5840
+ .cardText-first {
5841
+ font-weight: 600 !important;
5842
+ font-size: 0.88rem !important;
5843
+ line-height: 1.25 !important;
5844
+ color: #EDEDED !important;
5845
+ display: -webkit-box !important;
5846
+ -webkit-line-clamp: 2 !important;
5847
+ -webkit-box-orient: vertical !important;
5848
+ overflow: hidden !important;
5849
+ text-overflow: ellipsis !important;
5850
+ white-space: normal !important;
5851
+ max-height: 2.5em !important;
5852
+ margin-top: 6px !important;
5853
+ }
5854
+
5855
+ .cardText-secondary {
5856
+ font-size: 0.78rem !important;
5857
+ color: rgba(255, 255, 255, 0.55) !important;
5858
+ font-weight: 500 !important;
5859
+ margin-top: 2px !important;
5860
+ }
5861
+
5862
+ /* Section titles with modern streaming hierarchy */
5863
+ .sectionTitle {
5864
+ font-family: "Google Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
5865
+ font-weight: 700 !important;
5866
+ letter-spacing: -0.01em !important;
5867
+ font-size: 1.18rem !important;
5868
+ color: #FFFFFF !important;
5869
+ margin: 18px 0 10px 0 !important;
5870
+ display: inline-flex !important;
5871
+ align-items: center !important;
5872
+ }
5873
+
5874
+ .sectionTitleTextButton > .material-icons {
5875
+ color: rgba(255, 255, 255, 0.45) !important;
5876
+ font-size: 1.15rem !important;
5877
+ margin-left: 4px !important;
5878
+ transition: transform 0.2s ease, color 0.2s ease !important;
5879
+ }
5880
+
5881
+ .sectionTitleTextButton:hover > .material-icons {
5882
+ color: #FFFFFF !important;
5883
+ transform: translateX(3px) !important;
5884
+ }
apex/ui/spotlight-loader.js CHANGED
@@ -872,9 +872,11 @@ function findHomeTab() {
872
  // 1.5 Suppress and purge floating Play / Shuffle buttons from catalog/library views
873
  var strayPlayBtns = document.querySelectorAll(
874
  ':is(.view, .page, [data-role="page"], .libraryPage):not(#itemDetailPage):not(#videoOsdPage) :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"], button[title*="Play all" i], button[title*="Shuffle all" i]), ' +
875
- '.viewSettings :is(.btnPlay, .btnShuffle, button[data-action="play"], button[data-action="shuffle"]), ' +
876
  '.pageTitleWithDefaultButton :is(.btnPlay, .btnShuffle), ' +
877
- '.mainTabsContainer :is(.btnPlay, .btnShuffle)'
 
 
878
  );
879
  for (var sp = 0; sp < strayPlayBtns.length; sp++) {
880
  strayPlayBtns[sp].style.setProperty("display", "none", "important");
@@ -949,30 +951,44 @@ function findHomeTab() {
949
 
950
  function normalizeContinueWatchingCards() {
951
  safe(function () {
952
- var resumeContainers = document.querySelectorAll('.resumeSection, .nextUpSection, div[data-category="resume"], div[data-category="nextup"], #indexPage .itemsContainer-slider');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
953
  for (var rc = 0; rc < resumeContainers.length; rc++) {
954
  var cards = resumeContainers[rc].querySelectorAll('.card');
955
  for (var c = 0; c < cards.length; c++) {
956
  var card = cards[c];
957
- card.classList.remove('backdropCard', 'overflowBackdropCard', 'smallBackdropCard');
958
- card.classList.add('portraitCard');
959
- card.style.width = '140px';
960
- card.style.maxWidth = '140px';
961
- card.style.minWidth = '140px';
962
- card.style.flex = '0 0 140px';
963
 
964
  var padders = card.querySelectorAll('.cardPadder');
965
  for (var p = 0; p < padders.length; p++) {
966
- padders[p].classList.remove('cardPadder-backdrop', 'cardPadder-overflowBackdrop', 'cardPadder-smallBackdrop');
967
- padders[p].classList.add('cardPadder-portrait');
968
- padders[p].style.paddingBottom = '150%';
969
- padders[p].style.aspectRatio = '2 / 3';
970
  padders[p].style.height = '0';
971
  }
972
 
973
  var scalables = card.querySelectorAll('.cardScalable');
974
  for (var s = 0; s < scalables.length; s++) {
975
- scalables[s].style.aspectRatio = '2 / 3';
976
  scalables[s].style.borderRadius = '12px';
977
  scalables[s].style.overflow = 'hidden';
978
  }
 
872
  // 1.5 Suppress and purge floating Play / Shuffle buttons from catalog/library views
873
  var strayPlayBtns = document.querySelectorAll(
874
  ':is(.view, .page, [data-role="page"], .libraryPage):not(#itemDetailPage):not(#videoOsdPage) :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"], button[title*="Play all" i], button[title*="Shuffle all" i]), ' +
875
+ '.viewSettings :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"], button[data-action="play"], button[data-action="shuffle"]), ' +
876
  '.pageTitleWithDefaultButton :is(.btnPlay, .btnShuffle), ' +
877
+ '.mainTabsContainer :is(.btnPlay, .btnShuffle), ' +
878
+ '#moviesPage :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"]), ' +
879
+ '#tvShowsPage :is(.btnPlay, .btnShuffle, button[data-action="playall"], button[data-action="shuffleall"])'
880
  );
881
  for (var sp = 0; sp < strayPlayBtns.length; sp++) {
882
  strayPlayBtns[sp].style.setProperty("display", "none", "important");
 
951
 
952
  function normalizeContinueWatchingCards() {
953
  safe(function () {
954
+ // 1. Hide redundant "My Media" folder row on Home feed
955
+ var myMedia = document.querySelectorAll(
956
+ '#indexPage .verticalSection:has([data-type="CollectionFolder"]), ' +
957
+ '#indexPage .verticalSection:has([data-type="UserView"]), ' +
958
+ '#indexPage .verticalSection:has(.card[data-type="CollectionFolder"]), ' +
959
+ '#indexPage .verticalSection:has(.card[data-type="UserView"]), ' +
960
+ '#indexPage [data-category="views"], ' +
961
+ '#indexPage .section0'
962
+ );
963
+ for (var mm = 0; mm < myMedia.length; mm++) {
964
+ myMedia[mm].style.setProperty("display", "none", "important");
965
+ }
966
+
967
+ // 2. Format Continue Watching and Next Up as true 16:9 widescreen landscape cards
968
+ var resumeContainers = document.querySelectorAll('.resumeSection, .nextUpSection, div[data-category="resume"], div[data-category="nextup"]');
969
  for (var rc = 0; rc < resumeContainers.length; rc++) {
970
  var cards = resumeContainers[rc].querySelectorAll('.card');
971
  for (var c = 0; c < cards.length; c++) {
972
  var card = cards[c];
973
+ card.classList.remove('portraitCard', 'overflowBackdropCard', 'smallBackdropCard');
974
+ card.classList.add('backdropCard');
975
+ card.style.width = '';
976
+ card.style.maxWidth = '';
977
+ card.style.minWidth = '';
978
+ card.style.flex = '';
979
 
980
  var padders = card.querySelectorAll('.cardPadder');
981
  for (var p = 0; p < padders.length; p++) {
982
+ padders[p].classList.remove('cardPadder-portrait');
983
+ padders[p].classList.add('cardPadder-backdrop');
984
+ padders[p].style.paddingBottom = '56.25%';
985
+ padders[p].style.aspectRatio = '16 / 9';
986
  padders[p].style.height = '0';
987
  }
988
 
989
  var scalables = card.querySelectorAll('.cardScalable');
990
  for (var s = 0; s < scalables.length; s++) {
991
+ scalables[s].style.aspectRatio = '16 / 9';
992
  scalables[s].style.borderRadius = '12px';
993
  scalables[s].style.overflow = 'hidden';
994
  }