Skip to content

Commit a815336

Browse files
committed
refactor: simplify playlist menu item retrieval and enhance UI update logic with content change detection
1 parent 1f6a09b commit a815336

4 files changed

Lines changed: 60 additions & 62 deletions

File tree

packages/video-player/javascript/modules/playlist/playlist-menu-item.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class PlaylistMenuItem extends Component {
6666
}
6767
}
6868

69-
private getItem() {
69+
getItem() {
7070
return this.options_.item;
7171
}
7272

packages/video-player/javascript/modules/playlist/playlist-menu.ts

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { PlaylistMenuItem } from './playlist-menu-item';
66
import { Playlist } from './playlist';
77
import { IKPlayerOptions } from '../../interfaces';
88
import { CleanupRegistry } from '../../utils';
9+
import { isEqual, pick } from 'lodash';
10+
import { SOURCE_OPTION_KEYS } from './utils';
911

1012
const Component = videojs.getComponent('Component') as typeof ComponentType;
1113

@@ -78,48 +80,58 @@ export class PlaylistMenu extends Component {
7880

7981
/** Render or re-render the playlist UI */
8082
private update(): void {
81-
// Guard: if el_ doesn’t exist yet, skip
8283
if (!this.el_) return;
8384

84-
this.empty_();
85-
8685
const items = this.playlist.getItems();
87-
const listEl = document.createElement('ol');
88-
listEl.className = 'vjs-playlist-item-list';
89-
this.el_.appendChild(listEl);
90-
91-
this.items = items.map((item, index) => {
92-
const menuItem = new PlaylistMenuItem(
93-
this.player_,
94-
this.playlist,
95-
{
96-
item,
97-
showDescription: this.options_.showDescription,
98-
playOnSelect: this.options_.playOnSelect,
99-
},
100-
this.playerOptions
101-
);
102-
listEl.appendChild(menuItem.el_);
103-
return menuItem;
104-
});
86+
const currentIndex = this.playlist.getCurrentIndex?.() ?? 0;
87+
88+
const contentChanged =
89+
this.items.length !== items.length ||
90+
this.items.some((mi, i) => {
91+
const menuItem = mi.getItem();
92+
const playlistItem = items[i];
93+
return !isEqual(
94+
pick(menuItem, SOURCE_OPTION_KEYS),
95+
pick(playlistItem, SOURCE_OPTION_KEYS)
96+
);
97+
});
98+
99+
if (contentChanged) {
100+
this.empty_();
101+
102+
const listEl = document.createElement('ol');
103+
listEl.className = 'vjs-playlist-item-list';
104+
this.el_.appendChild(listEl);
105+
106+
this.items = items.map((item, index) => {
107+
const menuItem = new PlaylistMenuItem(
108+
this.player_,
109+
this.playlist,
110+
{
111+
item,
112+
showDescription: this.options_.showDescription,
113+
playOnSelect: this.options_.playOnSelect,
114+
},
115+
this.playerOptions
116+
);
117+
listEl.appendChild(menuItem.el_);
118+
return menuItem;
119+
});
120+
}
105121

106-
// Highlight current and up-next
107-
const current = this.playlist.getCurrentIndex?.() ?? 0;
108122
this.items.forEach((mi, i) => {
109-
if (i === current) {
123+
const thumbnail = mi.el_.querySelector('.vjs-playlist-thumbnail');
124+
if (i === currentIndex) {
110125
addSelectedClass(mi);
111-
videojs.dom.addClass(
112-
mi.el_.querySelector('.vjs-playlist-thumbnail')!,
113-
'vjs-playlist-now-playing'
114-
);
126+
if (thumbnail) {
127+
videojs.dom.addClass(thumbnail, 'vjs-playlist-now-playing');
128+
}
115129
} else {
116130
removeSelectedClass(mi);
131+
if (thumbnail) {
132+
videojs.dom.removeClass(thumbnail, 'vjs-playlist-now-playing');
133+
}
117134
}
118-
// if (i === current + 1) {
119-
// upNext(mi);
120-
// } else {
121-
// notUpNext(mi);
122-
// }
123135
});
124136
}
125137

packages/video-player/javascript/modules/playlist/styles/playlist-ui.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@
160160
flex: 0 0 clamp(40px, 50%, 80px);
161161
min-width: 0;
162162
}
163+
164+
.vjs-playlist-item.vjs-selected {
165+
166+
&::before {
167+
left: calc(var(--playlist-item-padding-left));
168+
}
169+
}
163170
}
164171

165172

packages/video-player/javascript/modules/shoppable/shoppable.css

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
/* This class on the main player shrinks the video to make space */
21
.video-js.shoppable-panel-visible .vjs-control-bar {
32
width: 80% !important;
43
transition: width 0.35s ease-in-out;
54
}
65

7-
/* The bar's main container */
86
.vjs-shoppable-bar {
97
position: absolute;
108
top: 0;
@@ -16,7 +14,6 @@
1614
z-index: 10;
1715
}
1816

19-
/* The inner container that holds the panel and toggle */
2017
.vjs-shoppable-bar-inner {
2118
position: absolute;
2219
top: 0;
@@ -37,7 +34,6 @@
3734
transition: none;
3835
}
3936

40-
/* The panel containing the products */
4137
.vjs-shoppable-panel {
4238
position: absolute;
4339
top: 0;
@@ -54,7 +50,6 @@
5450
display: none;
5551
}
5652

57-
/* The toggle button */
5853
.vjs-shoppable-toggle {
5954
position: absolute;
6055
top: 15px;
@@ -113,7 +108,6 @@
113108

114109
/* --- Item Layout --- */
115110

116-
/* 1. The main item is now a flex column container */
117111
.vjs-shoppable-item {
118112
display: flex;
119113
flex-direction: column;
@@ -135,14 +129,12 @@
135129
border-color: #2563eb;
136130
}
137131

138-
/* 2. NEW container for the image area to define shape and stacking context */
139132
.vjs-shoppable-image-container {
140133
position: relative;
141134
width: 100%;
142135
aspect-ratio: 1 / 1;
143136
}
144137

145-
/* 3. Both images are stacked absolutely inside the new image container */
146138
.vjs-shoppable-item-img {
147139
position: absolute;
148140
top: 0;
@@ -162,7 +154,6 @@
162154
opacity: 1;
163155
}
164156

165-
/* 4. The info block is a normal element that appears below the image container */
166157
.vjs-shoppable-item-info {
167158
position: static;
168159
width: 100%;
@@ -181,31 +172,27 @@
181172
justify-content: center;
182173
}
183174

184-
/* Add these properties to the rule above */
185175
.vjs-shoppable-postplay-carousel .vjs-shoppable-item-info {
186176
font-size: 14px;
187177
font-weight: 500;
188178
line-height: 1.3;
189179
background: rgba(0, 0, 0, 1);
190-
191-
/* --- ADD THESE LINES --- */
192-
height: 3.5em; /* Give all info blocks a fixed height (adjust value as needed) */
180+
height: 3.5em;
193181
display: flex;
194-
align-items: center; /* Vertically centers the text */
195-
justify-content: center; /* Horizontally centers the text */
182+
align-items: center;
183+
justify-content: center;
196184
}
197185

198186
.vjs-shoppable-postplay-carousel .vjs-shoppable-item {
199-
width: 200px; /* Fixed width for post-play carousel items */
200-
flex-shrink: 0; /* Prevents items from shrinking */
201-
border: 1px solid rgba(255, 255, 255, 0.4); /* Optional: adds a border for visibility */
187+
width: 200px;
188+
flex-shrink: 0;
189+
border: 1px solid rgba(255, 255, 255, 0.4);
202190
}
203191

204192
.vjs-shoppable-postplay-carousel .vjs-shoppable-item:hover {
205-
border: 1px solid rgba(255, 255, 255, 1); /* Optional: adds a border for visibility */
193+
border: 1px solid rgba(255, 255, 255, 1);
206194
}
207195

208-
/* 5. The hover overlay for text now covers the image container */
209196
.vjs-shoppable-item-overlay {
210197
position: absolute;
211198
top: 0;
@@ -270,35 +257,27 @@
270257
pointer-events: none;
271258
}
272259

273-
/* Tooltip on Top (Default) */
274260
.vjs-shoppable-hotspot-tooltip.tooltip-position-top {
275261
top: -8px;
276-
/* Add some space from the hotspot */
277262
left: 50%;
278263
transform: translate(-50%, -100%);
279264
}
280265

281-
/* Tooltip on the Bottom */
282266
.vjs-shoppable-hotspot-tooltip.tooltip-position-bottom {
283267
bottom: -8px;
284-
/* Add some space from the hotspot */
285268
left: 50%;
286269
transform: translate(-50%, 100%);
287270
}
288271

289-
/* Tooltip on the Left */
290272
.vjs-shoppable-hotspot-tooltip.tooltip-position-left {
291273
top: 50%;
292274
left: -8px;
293-
/* Add some space from the hotspot */
294275
transform: translate(-100%, -50%);
295276
}
296277

297-
/* Tooltip on the Right */
298278
.vjs-shoppable-hotspot-tooltip.tooltip-position-right {
299279
top: 50%;
300280
right: -8px;
301-
/* Add some space from the hotspot */
302281
transform: translate(100%, -50%);
303282
}
304283

0 commit comments

Comments
 (0)