@shortkitsdk/web 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/shortkit.cjs +237 -52
- package/dist/shortkit.js +237 -52
- package/dist/shortkit.min.js +1 -1
- package/dist/shortkit.mjs +237 -52
- package/dist/shortkit.slim.cjs +237 -52
- package/dist/shortkit.slim.js +237 -52
- package/dist/shortkit.slim.min.js +1 -1
- package/dist/shortkit.slim.mjs +237 -52
- package/package.json +1 -1
package/dist/shortkit.slim.mjs
CHANGED
|
@@ -599,16 +599,35 @@ class PlayerPool {
|
|
|
599
599
|
player._skCurrentUrl = streamingUrl;
|
|
600
600
|
}
|
|
601
601
|
/**
|
|
602
|
-
* Promote a preload player to active: raise buffer limits
|
|
603
|
-
*
|
|
602
|
+
* Promote a preload player to active: raise buffer limits, uncap ABR, and
|
|
603
|
+
* force an immediate quality upgrade.
|
|
604
|
+
*
|
|
605
|
+
* Preload streams start at level 0 (lowest rendition) to conserve bandwidth.
|
|
606
|
+
* When attachStream() is called again with isActive=true for the same URL it
|
|
607
|
+
* early-returns, so the HLS instance keeps its startLevel:0 config. The
|
|
608
|
+
* already-buffered low-quality segments play through before any higher-quality
|
|
609
|
+
* segments arrive — causing a visible low-res start even on fast connections.
|
|
610
|
+
*
|
|
611
|
+
* Fix: lock HLS to the highest level, then seek-in-place to flush the
|
|
612
|
+
* low-quality buffer so the player immediately re-fetches at high quality.
|
|
613
|
+
* Re-enable ABR after a few seconds so slow connections self-correct.
|
|
604
614
|
*/
|
|
605
615
|
promoteToActive(itemId) {
|
|
606
616
|
const hls = this.hlsInstances.get(itemId);
|
|
607
|
-
if (hls)
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
617
|
+
if (!hls) return;
|
|
618
|
+
hls.config.maxBufferLength = PlayerPool.ACTIVE_HLS_CONFIG.maxBufferLength;
|
|
619
|
+
hls.config.maxMaxBufferLength = PlayerPool.ACTIVE_HLS_CONFIG.maxMaxBufferLength;
|
|
620
|
+
hls.autoLevelCapping = -1;
|
|
621
|
+
const top = hls.levels ? hls.levels.length - 1 : -1;
|
|
622
|
+
if (top > 0 && hls.currentLevel < top) {
|
|
623
|
+
hls.currentLevel = top;
|
|
624
|
+
const player = this.assignments.get(itemId);
|
|
625
|
+
if (player) {
|
|
626
|
+
player.currentTime = player.currentTime;
|
|
627
|
+
}
|
|
628
|
+
setTimeout(() => {
|
|
629
|
+
if (!hls.destroyed) hls.currentLevel = -1;
|
|
630
|
+
}, 4e3);
|
|
612
631
|
}
|
|
613
632
|
}
|
|
614
633
|
/** Pause, destroy HLS, and remove player from DOM and pool tracking. */
|
|
@@ -904,7 +923,7 @@ class FeedManager {
|
|
|
904
923
|
}
|
|
905
924
|
setMuted(muted) {
|
|
906
925
|
this.isMuted = muted;
|
|
907
|
-
for (const [, player] of this.pool.
|
|
926
|
+
for (const [, player] of this.pool.assignments) {
|
|
908
927
|
player.muted = muted;
|
|
909
928
|
}
|
|
910
929
|
this._pushPlayerState({ isMuted: muted });
|
|
@@ -917,7 +936,7 @@ class FeedManager {
|
|
|
917
936
|
}
|
|
918
937
|
setPlaybackRate(rate) {
|
|
919
938
|
this.playbackRate = rate;
|
|
920
|
-
for (const [, player] of this.pool.
|
|
939
|
+
for (const [, player] of this.pool.assignments) {
|
|
921
940
|
player.playbackRate = rate;
|
|
922
941
|
}
|
|
923
942
|
this._pushPlayerState({ playbackRate: rate });
|
|
@@ -1394,11 +1413,10 @@ class FeedManager {
|
|
|
1394
1413
|
const player = this.pool.getPlayer(id);
|
|
1395
1414
|
if (player) {
|
|
1396
1415
|
player.pause();
|
|
1397
|
-
player.style.opacity = "0";
|
|
1398
1416
|
player._skRevealedFor = null;
|
|
1399
1417
|
}
|
|
1400
1418
|
this._stopTimeLoop(id);
|
|
1401
|
-
this.
|
|
1419
|
+
this._detachOverlay(id);
|
|
1402
1420
|
this._sk._tracker.deactivateContent();
|
|
1403
1421
|
}
|
|
1404
1422
|
// --- Time loop ---
|
|
@@ -1580,14 +1598,20 @@ class FeedManager {
|
|
|
1580
1598
|
}
|
|
1581
1599
|
}
|
|
1582
1600
|
/** Clear the overlay container's DOM and unsubscribe tracked listeners. */
|
|
1583
|
-
|
|
1601
|
+
/** Unsubscribe overlay event listeners without clearing DOM. */
|
|
1602
|
+
_detachOverlay(itemId) {
|
|
1584
1603
|
const entry = this._overlayContainers.get(itemId);
|
|
1585
1604
|
if (!entry) return;
|
|
1586
1605
|
if (entry.unsub) {
|
|
1587
1606
|
entry.unsub();
|
|
1588
1607
|
entry.unsub = null;
|
|
1589
1608
|
}
|
|
1590
|
-
|
|
1609
|
+
}
|
|
1610
|
+
/** Unsubscribe and clear overlay DOM (used on destroy). */
|
|
1611
|
+
_clearOverlay(itemId) {
|
|
1612
|
+
this._detachOverlay(itemId);
|
|
1613
|
+
const entry = this._overlayContainers.get(itemId);
|
|
1614
|
+
if (entry) entry.el.innerHTML = "";
|
|
1591
1615
|
}
|
|
1592
1616
|
}
|
|
1593
1617
|
class EmbeddedFeedManager {
|
|
@@ -1636,6 +1660,7 @@ class EmbeddedFeedManager {
|
|
|
1636
1660
|
this._setupScrollEnd();
|
|
1637
1661
|
this._setupVisibilityHandler();
|
|
1638
1662
|
this._setupCellHeightObserver();
|
|
1663
|
+
this._setupDebugPanel();
|
|
1639
1664
|
if (startIndex > 0 && startIndex < items.length) {
|
|
1640
1665
|
const targetEl = this.itemEls.get(items[startIndex].id);
|
|
1641
1666
|
if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
|
|
@@ -1658,6 +1683,11 @@ class EmbeddedFeedManager {
|
|
|
1658
1683
|
this._resizeObserver = null;
|
|
1659
1684
|
}
|
|
1660
1685
|
if (this._visHandler) document.removeEventListener("visibilitychange", this._visHandler);
|
|
1686
|
+
if (this._debugKeyHandler) document.removeEventListener("keydown", this._debugKeyHandler);
|
|
1687
|
+
if (this._debugPanel) {
|
|
1688
|
+
this._debugPanel.remove();
|
|
1689
|
+
this._debugPanel = null;
|
|
1690
|
+
}
|
|
1661
1691
|
this.container.innerHTML = "";
|
|
1662
1692
|
this.itemEls.clear();
|
|
1663
1693
|
this.items = [];
|
|
@@ -1701,7 +1731,7 @@ class EmbeddedFeedManager {
|
|
|
1701
1731
|
}
|
|
1702
1732
|
setMuted(muted) {
|
|
1703
1733
|
this.isMuted = muted;
|
|
1704
|
-
for (const [, player] of this.pool.
|
|
1734
|
+
for (const [, player] of this.pool.assignments) {
|
|
1705
1735
|
player.muted = muted;
|
|
1706
1736
|
}
|
|
1707
1737
|
this._pushPlayerState({ isMuted: muted });
|
|
@@ -1714,7 +1744,7 @@ class EmbeddedFeedManager {
|
|
|
1714
1744
|
}
|
|
1715
1745
|
setPlaybackRate(rate) {
|
|
1716
1746
|
this.playbackRate = rate;
|
|
1717
|
-
for (const [, player] of this.pool.
|
|
1747
|
+
for (const [, player] of this.pool.assignments) {
|
|
1718
1748
|
player.playbackRate = rate;
|
|
1719
1749
|
}
|
|
1720
1750
|
this._pushPlayerState({ playbackRate: rate });
|
|
@@ -1986,11 +2016,52 @@ class EmbeddedFeedManager {
|
|
|
1986
2016
|
const p = this.pool.getPlayer(id);
|
|
1987
2017
|
if (p) {
|
|
1988
2018
|
p.pause();
|
|
1989
|
-
p.style.opacity = "0";
|
|
1990
2019
|
p._skRevealedFor = null;
|
|
1991
2020
|
}
|
|
1992
2021
|
this._stopTimeLoop(id);
|
|
1993
|
-
this.
|
|
2022
|
+
this._detachOverlay(id);
|
|
2023
|
+
}
|
|
2024
|
+
// --- Debug panel (toggle with 'D' key) ---
|
|
2025
|
+
_setupDebugPanel() {
|
|
2026
|
+
const panel = document.createElement("div");
|
|
2027
|
+
panel.id = "sk-debug-panel";
|
|
2028
|
+
panel.style.cssText = "position:fixed;top:12px;right:12px;z-index:99999;background:rgba(0,0,0,.85);color:#0f0;font:12px/1.5 monospace;padding:10px 14px;border-radius:8px;pointer-events:none;display:none;min-width:220px;";
|
|
2029
|
+
document.body.appendChild(panel);
|
|
2030
|
+
this._debugPanel = panel;
|
|
2031
|
+
this._debugVisible = false;
|
|
2032
|
+
this._debugKeyHandler = (e) => {
|
|
2033
|
+
if (e.key === "d" || e.key === "D") {
|
|
2034
|
+
this._debugVisible = !this._debugVisible;
|
|
2035
|
+
panel.style.display = this._debugVisible ? "block" : "none";
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
document.addEventListener("keydown", this._debugKeyHandler);
|
|
2039
|
+
}
|
|
2040
|
+
_updateDebugPanel() {
|
|
2041
|
+
if (!this._debugVisible || !this._debugPanel) return;
|
|
2042
|
+
const hls = this.pool.hlsInstances.get(this.activeItemId);
|
|
2043
|
+
if (!hls || !hls.levels || !hls.levels.length) {
|
|
2044
|
+
this._debugPanel.innerHTML = "HLS: no levels loaded";
|
|
2045
|
+
return;
|
|
2046
|
+
}
|
|
2047
|
+
const level = hls.levels[hls.currentLevel] || {};
|
|
2048
|
+
const bw = hls.bandwidthEstimate ? (hls.bandwidthEstimate / 1e6).toFixed(2) : "?";
|
|
2049
|
+
const lines = [
|
|
2050
|
+
`<b style="color:#fff">HLS Debug</b>`,
|
|
2051
|
+
`Level: ${hls.currentLevel} / ${hls.levels.length - 1}`,
|
|
2052
|
+
`Resolution: ${level.width || "?"}x${level.height || "?"}`,
|
|
2053
|
+
`Bitrate: ${level.bitrate ? (level.bitrate / 1e3).toFixed(0) + " kbps" : "?"}`,
|
|
2054
|
+
`BW estimate: ${bw} Mbps`,
|
|
2055
|
+
`Auto cap: ${hls.autoLevelCapping}`,
|
|
2056
|
+
`Next level: ${hls.nextLevel}`,
|
|
2057
|
+
`<span style="color:#888">Levels:</span>`
|
|
2058
|
+
];
|
|
2059
|
+
for (let i = 0; i < hls.levels.length; i++) {
|
|
2060
|
+
const l = hls.levels[i];
|
|
2061
|
+
const marker = i === hls.currentLevel ? ' <b style="color:#0ff">◀</b>' : "";
|
|
2062
|
+
lines.push(` ${i}: ${l.width}x${l.height} @ ${(l.bitrate / 1e3).toFixed(0)}k${marker}`);
|
|
2063
|
+
}
|
|
2064
|
+
this._debugPanel.innerHTML = lines.join("<br>");
|
|
1994
2065
|
}
|
|
1995
2066
|
// --- Time loop (state emission only, no DOM updates) ---
|
|
1996
2067
|
_startTimeLoop(id, el, player) {
|
|
@@ -1998,6 +2069,7 @@ class EmbeddedFeedManager {
|
|
|
1998
2069
|
const tick = () => {
|
|
1999
2070
|
if (this._destroyed) return;
|
|
2000
2071
|
if (!player || player.paused) {
|
|
2072
|
+
this._updateDebugPanel();
|
|
2001
2073
|
this.rafIds.set(id, requestAnimationFrame(tick));
|
|
2002
2074
|
return;
|
|
2003
2075
|
}
|
|
@@ -2023,6 +2095,7 @@ class EmbeddedFeedManager {
|
|
|
2023
2095
|
player.play().catch(() => {
|
|
2024
2096
|
});
|
|
2025
2097
|
}
|
|
2098
|
+
this._updateDebugPanel();
|
|
2026
2099
|
this.rafIds.set(id, requestAnimationFrame(tick));
|
|
2027
2100
|
};
|
|
2028
2101
|
this.rafIds.set(id, requestAnimationFrame(tick));
|
|
@@ -2189,14 +2262,20 @@ class EmbeddedFeedManager {
|
|
|
2189
2262
|
} catch (e) {
|
|
2190
2263
|
}
|
|
2191
2264
|
}
|
|
2192
|
-
|
|
2265
|
+
/** Unsubscribe overlay event listeners without clearing DOM. */
|
|
2266
|
+
_detachOverlay(itemId) {
|
|
2193
2267
|
const entry = this._overlayContainers.get(itemId);
|
|
2194
2268
|
if (!entry) return;
|
|
2195
2269
|
if (entry.unsub) {
|
|
2196
2270
|
entry.unsub();
|
|
2197
2271
|
entry.unsub = null;
|
|
2198
2272
|
}
|
|
2199
|
-
|
|
2273
|
+
}
|
|
2274
|
+
/** Unsubscribe and clear overlay DOM (used on destroy). */
|
|
2275
|
+
_clearOverlay(itemId) {
|
|
2276
|
+
this._detachOverlay(itemId);
|
|
2277
|
+
const entry = this._overlayContainers.get(itemId);
|
|
2278
|
+
if (entry) entry.el.innerHTML = "";
|
|
2200
2279
|
}
|
|
2201
2280
|
}
|
|
2202
2281
|
const MuteOnSvg = '<svg viewBox="0 0 24 24"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/></svg>';
|
|
@@ -2546,6 +2625,7 @@ class PlayerFeedView {
|
|
|
2546
2625
|
this._isOpen = true;
|
|
2547
2626
|
this._onClose = onClose;
|
|
2548
2627
|
this._openItemId = item.id;
|
|
2628
|
+
this._openThumbnailUrl = item.thumbnailUrl || null;
|
|
2549
2629
|
const sourceRect = sourceEl.getBoundingClientRect();
|
|
2550
2630
|
const sourceRadius = parseFloat(getComputedStyle(sourceEl).borderRadius) || 12;
|
|
2551
2631
|
this.overlayEl.classList.add("skp-active");
|
|
@@ -2590,6 +2670,21 @@ class PlayerFeedView {
|
|
|
2590
2670
|
feedEl.style.transform = "none";
|
|
2591
2671
|
feedEl.style.borderRadius = `${targetRadius}px`;
|
|
2592
2672
|
});
|
|
2673
|
+
this.feedManager.startObserver();
|
|
2674
|
+
this.feedManager._activateItem(item.id);
|
|
2675
|
+
this.overlayEl.classList.add("skp-feed-ready");
|
|
2676
|
+
const itemOverlay = feedItemEl?.querySelector('[data-ref="overlay"]');
|
|
2677
|
+
const chromeEls = [...this.overlayEl.querySelectorAll(".skp-feed-close, .sk-sidebar")];
|
|
2678
|
+
if (itemOverlay) chromeEls.push(itemOverlay);
|
|
2679
|
+
chromeEls.forEach((el) => {
|
|
2680
|
+
el.style.opacity = "0";
|
|
2681
|
+
el.style.transition = "none";
|
|
2682
|
+
});
|
|
2683
|
+
this.overlayEl.getBoundingClientRect();
|
|
2684
|
+
chromeEls.forEach((el) => {
|
|
2685
|
+
el.style.transition = "opacity .35s cubic-bezier(.32,.72,0,1)";
|
|
2686
|
+
el.style.opacity = "1";
|
|
2687
|
+
});
|
|
2593
2688
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
2594
2689
|
feedEl.classList.remove("skp-flip-animating");
|
|
2595
2690
|
feedEl.style.transformOrigin = "";
|
|
@@ -2597,9 +2692,10 @@ class PlayerFeedView {
|
|
|
2597
2692
|
feedEl.style.scrollSnapType = "";
|
|
2598
2693
|
feedEl.style.transform = "";
|
|
2599
2694
|
feedEl.style.borderRadius = "";
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2695
|
+
chromeEls.forEach((el) => {
|
|
2696
|
+
el.style.opacity = "";
|
|
2697
|
+
el.style.transition = "";
|
|
2698
|
+
});
|
|
2603
2699
|
this._escHandler = (e) => {
|
|
2604
2700
|
if (e.key === "Escape") this.close();
|
|
2605
2701
|
};
|
|
@@ -2612,33 +2708,44 @@ class PlayerFeedView {
|
|
|
2612
2708
|
const feedWrapper = feedEl.parentNode;
|
|
2613
2709
|
const feedRect = feedEl.getBoundingClientRect();
|
|
2614
2710
|
const activeItemId = this.feedManager?.activeItemId;
|
|
2615
|
-
|
|
2616
|
-
if (activeItemId === this._openItemId) {
|
|
2617
|
-
const ejected = this.feedManager?.pool.ejectPlayer(activeItemId);
|
|
2618
|
-
if (ejected) {
|
|
2619
|
-
transferBack = true;
|
|
2620
|
-
transferVideo = ejected.video;
|
|
2621
|
-
transferHls = ejected.hls;
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2711
|
+
const canTransfer = activeItemId === this._openItemId;
|
|
2624
2712
|
let targetRect = null;
|
|
2625
2713
|
if (this._onClose) targetRect = this._onClose("getSourceRect");
|
|
2626
2714
|
if (feedRect && targetRect) {
|
|
2627
|
-
if (this.feedManager?.activeItemId && !
|
|
2715
|
+
if (this.feedManager?.activeItemId && !canTransfer) {
|
|
2628
2716
|
this.feedManager._deactivateItem(this.feedManager.activeItemId);
|
|
2629
2717
|
}
|
|
2718
|
+
const targetItemId = canTransfer ? this._openItemId : activeItemId;
|
|
2719
|
+
if (targetItemId && this.feedManager) {
|
|
2720
|
+
const targetEl = this.feedManager.itemEls.get(targetItemId);
|
|
2721
|
+
if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
|
|
2722
|
+
}
|
|
2723
|
+
const savedScrollTop = feedEl.scrollTop;
|
|
2630
2724
|
feedEl.style.position = "fixed";
|
|
2631
2725
|
feedEl.style.left = `${feedRect.left}px`;
|
|
2632
2726
|
feedEl.style.top = `${feedRect.top}px`;
|
|
2633
2727
|
feedEl.style.width = `${feedRect.width}px`;
|
|
2634
2728
|
feedEl.style.height = `${feedRect.height}px`;
|
|
2635
|
-
feedEl.style.zIndex =
|
|
2729
|
+
feedEl.style.zIndex = String(getComputedStyle(this.overlayEl).zIndex || 9999);
|
|
2636
2730
|
feedEl.style.margin = "0";
|
|
2637
2731
|
feedEl.style.flex = "none";
|
|
2638
2732
|
feedEl.style.aspectRatio = "unset";
|
|
2639
2733
|
feedEl.style.maxHeight = "none";
|
|
2640
2734
|
document.body.appendChild(feedEl);
|
|
2735
|
+
feedEl.scrollTop = savedScrollTop;
|
|
2641
2736
|
this.overlayEl.classList.remove("skp-active", "skp-feed-ready");
|
|
2737
|
+
let thumbOverlay = null;
|
|
2738
|
+
if (this._openThumbnailUrl) {
|
|
2739
|
+
const crossfadeItemId = canTransfer ? this._openItemId : activeItemId;
|
|
2740
|
+
const crossfadeEl = crossfadeItemId && this.feedManager?.itemEls.get(crossfadeItemId);
|
|
2741
|
+
const videoContainer = crossfadeEl?.querySelector('[data-ref="videoContainer"]');
|
|
2742
|
+
if (videoContainer) {
|
|
2743
|
+
thumbOverlay = document.createElement("img");
|
|
2744
|
+
thumbOverlay.src = this._openThumbnailUrl;
|
|
2745
|
+
thumbOverlay.style.cssText = "position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s cubic-bezier(.32,.72,0,1);pointer-events:none;z-index:2;";
|
|
2746
|
+
videoContainer.appendChild(thumbOverlay);
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2642
2749
|
const scaleX = targetRect.width / feedRect.width;
|
|
2643
2750
|
const scaleY = targetRect.height / feedRect.height;
|
|
2644
2751
|
const translateX = targetRect.left - feedRect.left;
|
|
@@ -2648,29 +2755,58 @@ class PlayerFeedView {
|
|
|
2648
2755
|
feedEl.style.transformOrigin = "0 0";
|
|
2649
2756
|
feedEl.style.overflow = "hidden";
|
|
2650
2757
|
feedEl.style.scrollSnapType = "none";
|
|
2758
|
+
feedEl.style.pointerEvents = "none";
|
|
2651
2759
|
feedEl.getBoundingClientRect();
|
|
2652
2760
|
feedEl.classList.add("skp-flip-animating");
|
|
2653
2761
|
requestAnimationFrame(() => {
|
|
2654
2762
|
feedEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
2655
2763
|
feedEl.style.borderRadius = `${endRadius}px`;
|
|
2764
|
+
if (thumbOverlay) thumbOverlay.style.opacity = "1";
|
|
2656
2765
|
});
|
|
2657
2766
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
2767
|
+
if (thumbOverlay) thumbOverlay.remove();
|
|
2768
|
+
let transferVideo = null;
|
|
2769
|
+
let transferHls = null;
|
|
2770
|
+
if (canTransfer) {
|
|
2771
|
+
const ejected = this.feedManager?.pool.ejectPlayer(this._openItemId);
|
|
2772
|
+
if (ejected) {
|
|
2773
|
+
transferVideo = ejected.video;
|
|
2774
|
+
transferHls = ejected.hls;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2658
2777
|
feedEl.style.visibility = "hidden";
|
|
2659
2778
|
feedEl.classList.remove("skp-flip-animating");
|
|
2660
|
-
["position", "left", "top", "width", "height", "zIndex", "margin", "flex", "aspectRatio", "maxHeight", "transformOrigin", "overflow", "scrollSnapType", "transform", "borderRadius"].forEach((p) => feedEl.style[p] = "");
|
|
2779
|
+
["position", "left", "top", "width", "height", "zIndex", "margin", "flex", "aspectRatio", "maxHeight", "transformOrigin", "overflow", "scrollSnapType", "pointerEvents", "transform", "borderRadius"].forEach((p) => feedEl.style[p] = "");
|
|
2661
2780
|
const sidebarEl = feedWrapper.querySelector(".sk-sidebar");
|
|
2662
2781
|
feedWrapper.insertBefore(feedEl, sidebarEl);
|
|
2663
2782
|
feedEl.style.visibility = "";
|
|
2783
|
+
if (this._onClose) {
|
|
2784
|
+
this._onClose("closed", {
|
|
2785
|
+
transferVideo,
|
|
2786
|
+
transferHls,
|
|
2787
|
+
transferItemId: transferVideo ? this._openItemId : null
|
|
2788
|
+
});
|
|
2789
|
+
this._onClose = null;
|
|
2790
|
+
}
|
|
2664
2791
|
} else {
|
|
2665
2792
|
this.overlayEl.classList.remove("skp-active", "skp-feed-ready");
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2793
|
+
if (this._onClose) {
|
|
2794
|
+
let transferVideo = null;
|
|
2795
|
+
let transferHls = null;
|
|
2796
|
+
if (canTransfer) {
|
|
2797
|
+
const ejected = this.feedManager?.pool.ejectPlayer(this._openItemId);
|
|
2798
|
+
if (ejected) {
|
|
2799
|
+
transferVideo = ejected.video;
|
|
2800
|
+
transferHls = ejected.hls;
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
this._onClose("closed", {
|
|
2804
|
+
transferVideo,
|
|
2805
|
+
transferHls,
|
|
2806
|
+
transferItemId: transferVideo ? this._openItemId : null
|
|
2807
|
+
});
|
|
2808
|
+
this._onClose = null;
|
|
2809
|
+
}
|
|
2674
2810
|
}
|
|
2675
2811
|
if (this.feedManager) {
|
|
2676
2812
|
this.feedManager.destroy();
|
|
@@ -2722,6 +2858,7 @@ class FeedView {
|
|
|
2722
2858
|
this._onClose = onClose;
|
|
2723
2859
|
this._openSlotIndex = startIndex;
|
|
2724
2860
|
this._openItemId = item.id;
|
|
2861
|
+
this._openThumbnailUrl = item.thumbnailUrl || null;
|
|
2725
2862
|
const slotRect = slotEl.getBoundingClientRect();
|
|
2726
2863
|
const slotRadius = parseFloat(getComputedStyle(slotEl).borderRadius) || 12;
|
|
2727
2864
|
if (_isPreview) {
|
|
@@ -2768,6 +2905,21 @@ class FeedView {
|
|
|
2768
2905
|
feedEl.style.transform = "none";
|
|
2769
2906
|
feedEl.style.borderRadius = `${targetRadius}px`;
|
|
2770
2907
|
});
|
|
2908
|
+
this.feedManager.startObserver();
|
|
2909
|
+
this.feedManager._activateItem(item.id);
|
|
2910
|
+
this.overlayEl.classList.add("skw-feed-ready");
|
|
2911
|
+
const itemOverlay = feedItemEl?.querySelector('[data-ref="overlay"]');
|
|
2912
|
+
const chromeEls = [...this.overlayEl.querySelectorAll(".skw-feed-close, .sk-sidebar")];
|
|
2913
|
+
if (itemOverlay) chromeEls.push(itemOverlay);
|
|
2914
|
+
chromeEls.forEach((el) => {
|
|
2915
|
+
el.style.opacity = "0";
|
|
2916
|
+
el.style.transition = "none";
|
|
2917
|
+
});
|
|
2918
|
+
this.overlayEl.getBoundingClientRect();
|
|
2919
|
+
chromeEls.forEach((el) => {
|
|
2920
|
+
el.style.transition = "opacity .35s cubic-bezier(.32,.72,0,1)";
|
|
2921
|
+
el.style.opacity = "1";
|
|
2922
|
+
});
|
|
2771
2923
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
2772
2924
|
feedEl.classList.remove("skw-flip-animating");
|
|
2773
2925
|
feedEl.style.transformOrigin = "";
|
|
@@ -2775,9 +2927,10 @@ class FeedView {
|
|
|
2775
2927
|
feedEl.style.scrollSnapType = "";
|
|
2776
2928
|
feedEl.style.transform = "";
|
|
2777
2929
|
feedEl.style.borderRadius = "";
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2930
|
+
chromeEls.forEach((el) => {
|
|
2931
|
+
el.style.opacity = "";
|
|
2932
|
+
el.style.transition = "";
|
|
2933
|
+
});
|
|
2781
2934
|
this._escHandler = (e) => {
|
|
2782
2935
|
if (e.key === "Escape") this.close();
|
|
2783
2936
|
};
|
|
@@ -2804,6 +2957,12 @@ class FeedView {
|
|
|
2804
2957
|
if (this.feedManager?.activeItemId && !canTransfer) {
|
|
2805
2958
|
this.feedManager._deactivateItem(this.feedManager.activeItemId);
|
|
2806
2959
|
}
|
|
2960
|
+
const targetItemId = canTransfer ? this._openItemId : activeItemId;
|
|
2961
|
+
if (targetItemId && this.feedManager) {
|
|
2962
|
+
const targetEl = this.feedManager.itemEls.get(targetItemId);
|
|
2963
|
+
if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
|
|
2964
|
+
}
|
|
2965
|
+
const savedScrollTop = feedEl.scrollTop;
|
|
2807
2966
|
feedEl.style.position = "fixed";
|
|
2808
2967
|
feedEl.style.left = `${feedRect.left}px`;
|
|
2809
2968
|
feedEl.style.top = `${feedRect.top}px`;
|
|
@@ -2815,7 +2974,20 @@ class FeedView {
|
|
|
2815
2974
|
feedEl.style.aspectRatio = "unset";
|
|
2816
2975
|
feedEl.style.maxHeight = "none";
|
|
2817
2976
|
document.body.appendChild(feedEl);
|
|
2977
|
+
feedEl.scrollTop = savedScrollTop;
|
|
2818
2978
|
this.overlayEl.classList.remove("skw-active", "skw-feed-ready");
|
|
2979
|
+
let thumbOverlay = null;
|
|
2980
|
+
if (this._openThumbnailUrl) {
|
|
2981
|
+
const targetItemId2 = canTransfer ? this._openItemId : activeItemId;
|
|
2982
|
+
const targetEl = targetItemId2 && this.feedManager?.itemEls.get(targetItemId2);
|
|
2983
|
+
const videoContainer = targetEl?.querySelector('[data-ref="videoContainer"]');
|
|
2984
|
+
if (videoContainer) {
|
|
2985
|
+
thumbOverlay = document.createElement("img");
|
|
2986
|
+
thumbOverlay.src = this._openThumbnailUrl;
|
|
2987
|
+
thumbOverlay.style.cssText = "position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s cubic-bezier(.32,.72,0,1);pointer-events:none;z-index:2;";
|
|
2988
|
+
videoContainer.appendChild(thumbOverlay);
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2819
2991
|
const slotRadius = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--skw-radius").trim()) || 12;
|
|
2820
2992
|
const scaleX = targetSlotRect.width / feedRect.width;
|
|
2821
2993
|
const scaleY = targetSlotRect.height / feedRect.height;
|
|
@@ -2825,13 +2997,16 @@ class FeedView {
|
|
|
2825
2997
|
feedEl.style.transformOrigin = "0 0";
|
|
2826
2998
|
feedEl.style.overflow = "hidden";
|
|
2827
2999
|
feedEl.style.scrollSnapType = "none";
|
|
3000
|
+
feedEl.style.pointerEvents = "none";
|
|
2828
3001
|
feedEl.getBoundingClientRect();
|
|
2829
3002
|
feedEl.classList.add("skw-flip-animating");
|
|
2830
3003
|
requestAnimationFrame(() => {
|
|
2831
3004
|
feedEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
2832
3005
|
feedEl.style.borderRadius = `${endRadius}px`;
|
|
3006
|
+
if (thumbOverlay) thumbOverlay.style.opacity = "1";
|
|
2833
3007
|
});
|
|
2834
3008
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
3009
|
+
if (thumbOverlay) thumbOverlay.remove();
|
|
2835
3010
|
let transferVideo = null;
|
|
2836
3011
|
let transferHls = null;
|
|
2837
3012
|
if (canTransfer) {
|
|
@@ -2856,6 +3031,7 @@ class FeedView {
|
|
|
2856
3031
|
feedEl.style.transformOrigin = "";
|
|
2857
3032
|
feedEl.style.overflow = "";
|
|
2858
3033
|
feedEl.style.scrollSnapType = "";
|
|
3034
|
+
feedEl.style.pointerEvents = "";
|
|
2859
3035
|
feedEl.style.transform = "";
|
|
2860
3036
|
feedEl.style.borderRadius = "";
|
|
2861
3037
|
feedWrapper.insertBefore(feedEl, feedWrapper.firstChild);
|
|
@@ -2985,11 +3161,20 @@ class WidgetPlayerPool {
|
|
|
2985
3161
|
}
|
|
2986
3162
|
promoteToActive(itemId) {
|
|
2987
3163
|
const hls = this.hlsInstances.get(itemId);
|
|
2988
|
-
if (hls)
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
3164
|
+
if (!hls) return;
|
|
3165
|
+
hls.config.maxBufferLength = WidgetPlayerPool.ACTIVE_HLS_CONFIG.maxBufferLength;
|
|
3166
|
+
hls.config.maxMaxBufferLength = WidgetPlayerPool.ACTIVE_HLS_CONFIG.maxMaxBufferLength;
|
|
3167
|
+
hls.autoLevelCapping = -1;
|
|
3168
|
+
const top = hls.levels ? hls.levels.length - 1 : -1;
|
|
3169
|
+
if (top > 0 && hls.currentLevel < top) {
|
|
3170
|
+
hls.currentLevel = top;
|
|
3171
|
+
const player = this.assignments.get(itemId);
|
|
3172
|
+
if (player) {
|
|
3173
|
+
player.currentTime = player.currentTime;
|
|
3174
|
+
}
|
|
3175
|
+
setTimeout(() => {
|
|
3176
|
+
if (!hls.destroyed) hls.currentLevel = -1;
|
|
3177
|
+
}, 4e3);
|
|
2993
3178
|
}
|
|
2994
3179
|
}
|
|
2995
3180
|
_destroyHls(itemId) {
|
|
@@ -3594,7 +3779,7 @@ const CSS = `
|
|
|
3594
3779
|
|
|
3595
3780
|
/* Video container */
|
|
3596
3781
|
.sk-video-container{position:absolute;inset:0;width:100%;height:100%;overflow:hidden;background-size:cover;background-position:center}
|
|
3597
|
-
.sk-video-container video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .
|
|
3782
|
+
.sk-video-container video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .35s ease}
|
|
3598
3783
|
|
|
3599
3784
|
/* Tap zone */
|
|
3600
3785
|
.sk-tap-zone{position:absolute;inset:0;z-index:3;cursor:pointer}
|
|
@@ -3610,7 +3795,7 @@ const CSS = `
|
|
|
3610
3795
|
|
|
3611
3796
|
/* Widget slot */
|
|
3612
3797
|
.skw-slot{position:relative;overflow:hidden;cursor:pointer}
|
|
3613
|
-
.skw-slot video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .
|
|
3798
|
+
.skw-slot video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s ease}
|
|
3614
3799
|
.skw-slot-thumb{position:absolute;inset:0;background-size:cover;background-position:center}
|
|
3615
3800
|
.skw-slot-overlay{position:absolute;inset:0;z-index:4;pointer-events:none}
|
|
3616
3801
|
.skw-slot-overlay>*{pointer-events:auto}
|