@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.cjs
CHANGED
|
@@ -601,16 +601,35 @@ class PlayerPool {
|
|
|
601
601
|
player._skCurrentUrl = streamingUrl;
|
|
602
602
|
}
|
|
603
603
|
/**
|
|
604
|
-
* Promote a preload player to active: raise buffer limits
|
|
605
|
-
*
|
|
604
|
+
* Promote a preload player to active: raise buffer limits, uncap ABR, and
|
|
605
|
+
* force an immediate quality upgrade.
|
|
606
|
+
*
|
|
607
|
+
* Preload streams start at level 0 (lowest rendition) to conserve bandwidth.
|
|
608
|
+
* When attachStream() is called again with isActive=true for the same URL it
|
|
609
|
+
* early-returns, so the HLS instance keeps its startLevel:0 config. The
|
|
610
|
+
* already-buffered low-quality segments play through before any higher-quality
|
|
611
|
+
* segments arrive — causing a visible low-res start even on fast connections.
|
|
612
|
+
*
|
|
613
|
+
* Fix: lock HLS to the highest level, then seek-in-place to flush the
|
|
614
|
+
* low-quality buffer so the player immediately re-fetches at high quality.
|
|
615
|
+
* Re-enable ABR after a few seconds so slow connections self-correct.
|
|
606
616
|
*/
|
|
607
617
|
promoteToActive(itemId) {
|
|
608
618
|
const hls = this.hlsInstances.get(itemId);
|
|
609
|
-
if (hls)
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
619
|
+
if (!hls) return;
|
|
620
|
+
hls.config.maxBufferLength = PlayerPool.ACTIVE_HLS_CONFIG.maxBufferLength;
|
|
621
|
+
hls.config.maxMaxBufferLength = PlayerPool.ACTIVE_HLS_CONFIG.maxMaxBufferLength;
|
|
622
|
+
hls.autoLevelCapping = -1;
|
|
623
|
+
const top = hls.levels ? hls.levels.length - 1 : -1;
|
|
624
|
+
if (top > 0 && hls.currentLevel < top) {
|
|
625
|
+
hls.currentLevel = top;
|
|
626
|
+
const player = this.assignments.get(itemId);
|
|
627
|
+
if (player) {
|
|
628
|
+
player.currentTime = player.currentTime;
|
|
629
|
+
}
|
|
630
|
+
setTimeout(() => {
|
|
631
|
+
if (!hls.destroyed) hls.currentLevel = -1;
|
|
632
|
+
}, 4e3);
|
|
614
633
|
}
|
|
615
634
|
}
|
|
616
635
|
/** Pause, destroy HLS, and remove player from DOM and pool tracking. */
|
|
@@ -906,7 +925,7 @@ class FeedManager {
|
|
|
906
925
|
}
|
|
907
926
|
setMuted(muted) {
|
|
908
927
|
this.isMuted = muted;
|
|
909
|
-
for (const [, player] of this.pool.
|
|
928
|
+
for (const [, player] of this.pool.assignments) {
|
|
910
929
|
player.muted = muted;
|
|
911
930
|
}
|
|
912
931
|
this._pushPlayerState({ isMuted: muted });
|
|
@@ -919,7 +938,7 @@ class FeedManager {
|
|
|
919
938
|
}
|
|
920
939
|
setPlaybackRate(rate) {
|
|
921
940
|
this.playbackRate = rate;
|
|
922
|
-
for (const [, player] of this.pool.
|
|
941
|
+
for (const [, player] of this.pool.assignments) {
|
|
923
942
|
player.playbackRate = rate;
|
|
924
943
|
}
|
|
925
944
|
this._pushPlayerState({ playbackRate: rate });
|
|
@@ -1396,11 +1415,10 @@ class FeedManager {
|
|
|
1396
1415
|
const player = this.pool.getPlayer(id);
|
|
1397
1416
|
if (player) {
|
|
1398
1417
|
player.pause();
|
|
1399
|
-
player.style.opacity = "0";
|
|
1400
1418
|
player._skRevealedFor = null;
|
|
1401
1419
|
}
|
|
1402
1420
|
this._stopTimeLoop(id);
|
|
1403
|
-
this.
|
|
1421
|
+
this._detachOverlay(id);
|
|
1404
1422
|
this._sk._tracker.deactivateContent();
|
|
1405
1423
|
}
|
|
1406
1424
|
// --- Time loop ---
|
|
@@ -1582,14 +1600,20 @@ class FeedManager {
|
|
|
1582
1600
|
}
|
|
1583
1601
|
}
|
|
1584
1602
|
/** Clear the overlay container's DOM and unsubscribe tracked listeners. */
|
|
1585
|
-
|
|
1603
|
+
/** Unsubscribe overlay event listeners without clearing DOM. */
|
|
1604
|
+
_detachOverlay(itemId) {
|
|
1586
1605
|
const entry = this._overlayContainers.get(itemId);
|
|
1587
1606
|
if (!entry) return;
|
|
1588
1607
|
if (entry.unsub) {
|
|
1589
1608
|
entry.unsub();
|
|
1590
1609
|
entry.unsub = null;
|
|
1591
1610
|
}
|
|
1592
|
-
|
|
1611
|
+
}
|
|
1612
|
+
/** Unsubscribe and clear overlay DOM (used on destroy). */
|
|
1613
|
+
_clearOverlay(itemId) {
|
|
1614
|
+
this._detachOverlay(itemId);
|
|
1615
|
+
const entry = this._overlayContainers.get(itemId);
|
|
1616
|
+
if (entry) entry.el.innerHTML = "";
|
|
1593
1617
|
}
|
|
1594
1618
|
}
|
|
1595
1619
|
class EmbeddedFeedManager {
|
|
@@ -1638,6 +1662,7 @@ class EmbeddedFeedManager {
|
|
|
1638
1662
|
this._setupScrollEnd();
|
|
1639
1663
|
this._setupVisibilityHandler();
|
|
1640
1664
|
this._setupCellHeightObserver();
|
|
1665
|
+
this._setupDebugPanel();
|
|
1641
1666
|
if (startIndex > 0 && startIndex < items.length) {
|
|
1642
1667
|
const targetEl = this.itemEls.get(items[startIndex].id);
|
|
1643
1668
|
if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
|
|
@@ -1660,6 +1685,11 @@ class EmbeddedFeedManager {
|
|
|
1660
1685
|
this._resizeObserver = null;
|
|
1661
1686
|
}
|
|
1662
1687
|
if (this._visHandler) document.removeEventListener("visibilitychange", this._visHandler);
|
|
1688
|
+
if (this._debugKeyHandler) document.removeEventListener("keydown", this._debugKeyHandler);
|
|
1689
|
+
if (this._debugPanel) {
|
|
1690
|
+
this._debugPanel.remove();
|
|
1691
|
+
this._debugPanel = null;
|
|
1692
|
+
}
|
|
1663
1693
|
this.container.innerHTML = "";
|
|
1664
1694
|
this.itemEls.clear();
|
|
1665
1695
|
this.items = [];
|
|
@@ -1703,7 +1733,7 @@ class EmbeddedFeedManager {
|
|
|
1703
1733
|
}
|
|
1704
1734
|
setMuted(muted) {
|
|
1705
1735
|
this.isMuted = muted;
|
|
1706
|
-
for (const [, player] of this.pool.
|
|
1736
|
+
for (const [, player] of this.pool.assignments) {
|
|
1707
1737
|
player.muted = muted;
|
|
1708
1738
|
}
|
|
1709
1739
|
this._pushPlayerState({ isMuted: muted });
|
|
@@ -1716,7 +1746,7 @@ class EmbeddedFeedManager {
|
|
|
1716
1746
|
}
|
|
1717
1747
|
setPlaybackRate(rate) {
|
|
1718
1748
|
this.playbackRate = rate;
|
|
1719
|
-
for (const [, player] of this.pool.
|
|
1749
|
+
for (const [, player] of this.pool.assignments) {
|
|
1720
1750
|
player.playbackRate = rate;
|
|
1721
1751
|
}
|
|
1722
1752
|
this._pushPlayerState({ playbackRate: rate });
|
|
@@ -1988,11 +2018,52 @@ class EmbeddedFeedManager {
|
|
|
1988
2018
|
const p = this.pool.getPlayer(id);
|
|
1989
2019
|
if (p) {
|
|
1990
2020
|
p.pause();
|
|
1991
|
-
p.style.opacity = "0";
|
|
1992
2021
|
p._skRevealedFor = null;
|
|
1993
2022
|
}
|
|
1994
2023
|
this._stopTimeLoop(id);
|
|
1995
|
-
this.
|
|
2024
|
+
this._detachOverlay(id);
|
|
2025
|
+
}
|
|
2026
|
+
// --- Debug panel (toggle with 'D' key) ---
|
|
2027
|
+
_setupDebugPanel() {
|
|
2028
|
+
const panel = document.createElement("div");
|
|
2029
|
+
panel.id = "sk-debug-panel";
|
|
2030
|
+
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;";
|
|
2031
|
+
document.body.appendChild(panel);
|
|
2032
|
+
this._debugPanel = panel;
|
|
2033
|
+
this._debugVisible = false;
|
|
2034
|
+
this._debugKeyHandler = (e) => {
|
|
2035
|
+
if (e.key === "d" || e.key === "D") {
|
|
2036
|
+
this._debugVisible = !this._debugVisible;
|
|
2037
|
+
panel.style.display = this._debugVisible ? "block" : "none";
|
|
2038
|
+
}
|
|
2039
|
+
};
|
|
2040
|
+
document.addEventListener("keydown", this._debugKeyHandler);
|
|
2041
|
+
}
|
|
2042
|
+
_updateDebugPanel() {
|
|
2043
|
+
if (!this._debugVisible || !this._debugPanel) return;
|
|
2044
|
+
const hls = this.pool.hlsInstances.get(this.activeItemId);
|
|
2045
|
+
if (!hls || !hls.levels || !hls.levels.length) {
|
|
2046
|
+
this._debugPanel.innerHTML = "HLS: no levels loaded";
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
2049
|
+
const level = hls.levels[hls.currentLevel] || {};
|
|
2050
|
+
const bw = hls.bandwidthEstimate ? (hls.bandwidthEstimate / 1e6).toFixed(2) : "?";
|
|
2051
|
+
const lines = [
|
|
2052
|
+
`<b style="color:#fff">HLS Debug</b>`,
|
|
2053
|
+
`Level: ${hls.currentLevel} / ${hls.levels.length - 1}`,
|
|
2054
|
+
`Resolution: ${level.width || "?"}x${level.height || "?"}`,
|
|
2055
|
+
`Bitrate: ${level.bitrate ? (level.bitrate / 1e3).toFixed(0) + " kbps" : "?"}`,
|
|
2056
|
+
`BW estimate: ${bw} Mbps`,
|
|
2057
|
+
`Auto cap: ${hls.autoLevelCapping}`,
|
|
2058
|
+
`Next level: ${hls.nextLevel}`,
|
|
2059
|
+
`<span style="color:#888">Levels:</span>`
|
|
2060
|
+
];
|
|
2061
|
+
for (let i = 0; i < hls.levels.length; i++) {
|
|
2062
|
+
const l = hls.levels[i];
|
|
2063
|
+
const marker = i === hls.currentLevel ? ' <b style="color:#0ff">◀</b>' : "";
|
|
2064
|
+
lines.push(` ${i}: ${l.width}x${l.height} @ ${(l.bitrate / 1e3).toFixed(0)}k${marker}`);
|
|
2065
|
+
}
|
|
2066
|
+
this._debugPanel.innerHTML = lines.join("<br>");
|
|
1996
2067
|
}
|
|
1997
2068
|
// --- Time loop (state emission only, no DOM updates) ---
|
|
1998
2069
|
_startTimeLoop(id, el, player) {
|
|
@@ -2000,6 +2071,7 @@ class EmbeddedFeedManager {
|
|
|
2000
2071
|
const tick = () => {
|
|
2001
2072
|
if (this._destroyed) return;
|
|
2002
2073
|
if (!player || player.paused) {
|
|
2074
|
+
this._updateDebugPanel();
|
|
2003
2075
|
this.rafIds.set(id, requestAnimationFrame(tick));
|
|
2004
2076
|
return;
|
|
2005
2077
|
}
|
|
@@ -2025,6 +2097,7 @@ class EmbeddedFeedManager {
|
|
|
2025
2097
|
player.play().catch(() => {
|
|
2026
2098
|
});
|
|
2027
2099
|
}
|
|
2100
|
+
this._updateDebugPanel();
|
|
2028
2101
|
this.rafIds.set(id, requestAnimationFrame(tick));
|
|
2029
2102
|
};
|
|
2030
2103
|
this.rafIds.set(id, requestAnimationFrame(tick));
|
|
@@ -2191,14 +2264,20 @@ class EmbeddedFeedManager {
|
|
|
2191
2264
|
} catch (e) {
|
|
2192
2265
|
}
|
|
2193
2266
|
}
|
|
2194
|
-
|
|
2267
|
+
/** Unsubscribe overlay event listeners without clearing DOM. */
|
|
2268
|
+
_detachOverlay(itemId) {
|
|
2195
2269
|
const entry = this._overlayContainers.get(itemId);
|
|
2196
2270
|
if (!entry) return;
|
|
2197
2271
|
if (entry.unsub) {
|
|
2198
2272
|
entry.unsub();
|
|
2199
2273
|
entry.unsub = null;
|
|
2200
2274
|
}
|
|
2201
|
-
|
|
2275
|
+
}
|
|
2276
|
+
/** Unsubscribe and clear overlay DOM (used on destroy). */
|
|
2277
|
+
_clearOverlay(itemId) {
|
|
2278
|
+
this._detachOverlay(itemId);
|
|
2279
|
+
const entry = this._overlayContainers.get(itemId);
|
|
2280
|
+
if (entry) entry.el.innerHTML = "";
|
|
2202
2281
|
}
|
|
2203
2282
|
}
|
|
2204
2283
|
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>';
|
|
@@ -2548,6 +2627,7 @@ class PlayerFeedView {
|
|
|
2548
2627
|
this._isOpen = true;
|
|
2549
2628
|
this._onClose = onClose;
|
|
2550
2629
|
this._openItemId = item.id;
|
|
2630
|
+
this._openThumbnailUrl = item.thumbnailUrl || null;
|
|
2551
2631
|
const sourceRect = sourceEl.getBoundingClientRect();
|
|
2552
2632
|
const sourceRadius = parseFloat(getComputedStyle(sourceEl).borderRadius) || 12;
|
|
2553
2633
|
this.overlayEl.classList.add("skp-active");
|
|
@@ -2592,6 +2672,21 @@ class PlayerFeedView {
|
|
|
2592
2672
|
feedEl.style.transform = "none";
|
|
2593
2673
|
feedEl.style.borderRadius = `${targetRadius}px`;
|
|
2594
2674
|
});
|
|
2675
|
+
this.feedManager.startObserver();
|
|
2676
|
+
this.feedManager._activateItem(item.id);
|
|
2677
|
+
this.overlayEl.classList.add("skp-feed-ready");
|
|
2678
|
+
const itemOverlay = feedItemEl?.querySelector('[data-ref="overlay"]');
|
|
2679
|
+
const chromeEls = [...this.overlayEl.querySelectorAll(".skp-feed-close, .sk-sidebar")];
|
|
2680
|
+
if (itemOverlay) chromeEls.push(itemOverlay);
|
|
2681
|
+
chromeEls.forEach((el) => {
|
|
2682
|
+
el.style.opacity = "0";
|
|
2683
|
+
el.style.transition = "none";
|
|
2684
|
+
});
|
|
2685
|
+
this.overlayEl.getBoundingClientRect();
|
|
2686
|
+
chromeEls.forEach((el) => {
|
|
2687
|
+
el.style.transition = "opacity .35s cubic-bezier(.32,.72,0,1)";
|
|
2688
|
+
el.style.opacity = "1";
|
|
2689
|
+
});
|
|
2595
2690
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
2596
2691
|
feedEl.classList.remove("skp-flip-animating");
|
|
2597
2692
|
feedEl.style.transformOrigin = "";
|
|
@@ -2599,9 +2694,10 @@ class PlayerFeedView {
|
|
|
2599
2694
|
feedEl.style.scrollSnapType = "";
|
|
2600
2695
|
feedEl.style.transform = "";
|
|
2601
2696
|
feedEl.style.borderRadius = "";
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2697
|
+
chromeEls.forEach((el) => {
|
|
2698
|
+
el.style.opacity = "";
|
|
2699
|
+
el.style.transition = "";
|
|
2700
|
+
});
|
|
2605
2701
|
this._escHandler = (e) => {
|
|
2606
2702
|
if (e.key === "Escape") this.close();
|
|
2607
2703
|
};
|
|
@@ -2614,33 +2710,44 @@ class PlayerFeedView {
|
|
|
2614
2710
|
const feedWrapper = feedEl.parentNode;
|
|
2615
2711
|
const feedRect = feedEl.getBoundingClientRect();
|
|
2616
2712
|
const activeItemId = this.feedManager?.activeItemId;
|
|
2617
|
-
|
|
2618
|
-
if (activeItemId === this._openItemId) {
|
|
2619
|
-
const ejected = this.feedManager?.pool.ejectPlayer(activeItemId);
|
|
2620
|
-
if (ejected) {
|
|
2621
|
-
transferBack = true;
|
|
2622
|
-
transferVideo = ejected.video;
|
|
2623
|
-
transferHls = ejected.hls;
|
|
2624
|
-
}
|
|
2625
|
-
}
|
|
2713
|
+
const canTransfer = activeItemId === this._openItemId;
|
|
2626
2714
|
let targetRect = null;
|
|
2627
2715
|
if (this._onClose) targetRect = this._onClose("getSourceRect");
|
|
2628
2716
|
if (feedRect && targetRect) {
|
|
2629
|
-
if (this.feedManager?.activeItemId && !
|
|
2717
|
+
if (this.feedManager?.activeItemId && !canTransfer) {
|
|
2630
2718
|
this.feedManager._deactivateItem(this.feedManager.activeItemId);
|
|
2631
2719
|
}
|
|
2720
|
+
const targetItemId = canTransfer ? this._openItemId : activeItemId;
|
|
2721
|
+
if (targetItemId && this.feedManager) {
|
|
2722
|
+
const targetEl = this.feedManager.itemEls.get(targetItemId);
|
|
2723
|
+
if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
|
|
2724
|
+
}
|
|
2725
|
+
const savedScrollTop = feedEl.scrollTop;
|
|
2632
2726
|
feedEl.style.position = "fixed";
|
|
2633
2727
|
feedEl.style.left = `${feedRect.left}px`;
|
|
2634
2728
|
feedEl.style.top = `${feedRect.top}px`;
|
|
2635
2729
|
feedEl.style.width = `${feedRect.width}px`;
|
|
2636
2730
|
feedEl.style.height = `${feedRect.height}px`;
|
|
2637
|
-
feedEl.style.zIndex =
|
|
2731
|
+
feedEl.style.zIndex = String(getComputedStyle(this.overlayEl).zIndex || 9999);
|
|
2638
2732
|
feedEl.style.margin = "0";
|
|
2639
2733
|
feedEl.style.flex = "none";
|
|
2640
2734
|
feedEl.style.aspectRatio = "unset";
|
|
2641
2735
|
feedEl.style.maxHeight = "none";
|
|
2642
2736
|
document.body.appendChild(feedEl);
|
|
2737
|
+
feedEl.scrollTop = savedScrollTop;
|
|
2643
2738
|
this.overlayEl.classList.remove("skp-active", "skp-feed-ready");
|
|
2739
|
+
let thumbOverlay = null;
|
|
2740
|
+
if (this._openThumbnailUrl) {
|
|
2741
|
+
const crossfadeItemId = canTransfer ? this._openItemId : activeItemId;
|
|
2742
|
+
const crossfadeEl = crossfadeItemId && this.feedManager?.itemEls.get(crossfadeItemId);
|
|
2743
|
+
const videoContainer = crossfadeEl?.querySelector('[data-ref="videoContainer"]');
|
|
2744
|
+
if (videoContainer) {
|
|
2745
|
+
thumbOverlay = document.createElement("img");
|
|
2746
|
+
thumbOverlay.src = this._openThumbnailUrl;
|
|
2747
|
+
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;";
|
|
2748
|
+
videoContainer.appendChild(thumbOverlay);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2644
2751
|
const scaleX = targetRect.width / feedRect.width;
|
|
2645
2752
|
const scaleY = targetRect.height / feedRect.height;
|
|
2646
2753
|
const translateX = targetRect.left - feedRect.left;
|
|
@@ -2650,29 +2757,58 @@ class PlayerFeedView {
|
|
|
2650
2757
|
feedEl.style.transformOrigin = "0 0";
|
|
2651
2758
|
feedEl.style.overflow = "hidden";
|
|
2652
2759
|
feedEl.style.scrollSnapType = "none";
|
|
2760
|
+
feedEl.style.pointerEvents = "none";
|
|
2653
2761
|
feedEl.getBoundingClientRect();
|
|
2654
2762
|
feedEl.classList.add("skp-flip-animating");
|
|
2655
2763
|
requestAnimationFrame(() => {
|
|
2656
2764
|
feedEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
2657
2765
|
feedEl.style.borderRadius = `${endRadius}px`;
|
|
2766
|
+
if (thumbOverlay) thumbOverlay.style.opacity = "1";
|
|
2658
2767
|
});
|
|
2659
2768
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
2769
|
+
if (thumbOverlay) thumbOverlay.remove();
|
|
2770
|
+
let transferVideo = null;
|
|
2771
|
+
let transferHls = null;
|
|
2772
|
+
if (canTransfer) {
|
|
2773
|
+
const ejected = this.feedManager?.pool.ejectPlayer(this._openItemId);
|
|
2774
|
+
if (ejected) {
|
|
2775
|
+
transferVideo = ejected.video;
|
|
2776
|
+
transferHls = ejected.hls;
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2660
2779
|
feedEl.style.visibility = "hidden";
|
|
2661
2780
|
feedEl.classList.remove("skp-flip-animating");
|
|
2662
|
-
["position", "left", "top", "width", "height", "zIndex", "margin", "flex", "aspectRatio", "maxHeight", "transformOrigin", "overflow", "scrollSnapType", "transform", "borderRadius"].forEach((p) => feedEl.style[p] = "");
|
|
2781
|
+
["position", "left", "top", "width", "height", "zIndex", "margin", "flex", "aspectRatio", "maxHeight", "transformOrigin", "overflow", "scrollSnapType", "pointerEvents", "transform", "borderRadius"].forEach((p) => feedEl.style[p] = "");
|
|
2663
2782
|
const sidebarEl = feedWrapper.querySelector(".sk-sidebar");
|
|
2664
2783
|
feedWrapper.insertBefore(feedEl, sidebarEl);
|
|
2665
2784
|
feedEl.style.visibility = "";
|
|
2785
|
+
if (this._onClose) {
|
|
2786
|
+
this._onClose("closed", {
|
|
2787
|
+
transferVideo,
|
|
2788
|
+
transferHls,
|
|
2789
|
+
transferItemId: transferVideo ? this._openItemId : null
|
|
2790
|
+
});
|
|
2791
|
+
this._onClose = null;
|
|
2792
|
+
}
|
|
2666
2793
|
} else {
|
|
2667
2794
|
this.overlayEl.classList.remove("skp-active", "skp-feed-ready");
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2795
|
+
if (this._onClose) {
|
|
2796
|
+
let transferVideo = null;
|
|
2797
|
+
let transferHls = null;
|
|
2798
|
+
if (canTransfer) {
|
|
2799
|
+
const ejected = this.feedManager?.pool.ejectPlayer(this._openItemId);
|
|
2800
|
+
if (ejected) {
|
|
2801
|
+
transferVideo = ejected.video;
|
|
2802
|
+
transferHls = ejected.hls;
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
this._onClose("closed", {
|
|
2806
|
+
transferVideo,
|
|
2807
|
+
transferHls,
|
|
2808
|
+
transferItemId: transferVideo ? this._openItemId : null
|
|
2809
|
+
});
|
|
2810
|
+
this._onClose = null;
|
|
2811
|
+
}
|
|
2676
2812
|
}
|
|
2677
2813
|
if (this.feedManager) {
|
|
2678
2814
|
this.feedManager.destroy();
|
|
@@ -2724,6 +2860,7 @@ class FeedView {
|
|
|
2724
2860
|
this._onClose = onClose;
|
|
2725
2861
|
this._openSlotIndex = startIndex;
|
|
2726
2862
|
this._openItemId = item.id;
|
|
2863
|
+
this._openThumbnailUrl = item.thumbnailUrl || null;
|
|
2727
2864
|
const slotRect = slotEl.getBoundingClientRect();
|
|
2728
2865
|
const slotRadius = parseFloat(getComputedStyle(slotEl).borderRadius) || 12;
|
|
2729
2866
|
if (_isPreview) {
|
|
@@ -2770,6 +2907,21 @@ class FeedView {
|
|
|
2770
2907
|
feedEl.style.transform = "none";
|
|
2771
2908
|
feedEl.style.borderRadius = `${targetRadius}px`;
|
|
2772
2909
|
});
|
|
2910
|
+
this.feedManager.startObserver();
|
|
2911
|
+
this.feedManager._activateItem(item.id);
|
|
2912
|
+
this.overlayEl.classList.add("skw-feed-ready");
|
|
2913
|
+
const itemOverlay = feedItemEl?.querySelector('[data-ref="overlay"]');
|
|
2914
|
+
const chromeEls = [...this.overlayEl.querySelectorAll(".skw-feed-close, .sk-sidebar")];
|
|
2915
|
+
if (itemOverlay) chromeEls.push(itemOverlay);
|
|
2916
|
+
chromeEls.forEach((el) => {
|
|
2917
|
+
el.style.opacity = "0";
|
|
2918
|
+
el.style.transition = "none";
|
|
2919
|
+
});
|
|
2920
|
+
this.overlayEl.getBoundingClientRect();
|
|
2921
|
+
chromeEls.forEach((el) => {
|
|
2922
|
+
el.style.transition = "opacity .35s cubic-bezier(.32,.72,0,1)";
|
|
2923
|
+
el.style.opacity = "1";
|
|
2924
|
+
});
|
|
2773
2925
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
2774
2926
|
feedEl.classList.remove("skw-flip-animating");
|
|
2775
2927
|
feedEl.style.transformOrigin = "";
|
|
@@ -2777,9 +2929,10 @@ class FeedView {
|
|
|
2777
2929
|
feedEl.style.scrollSnapType = "";
|
|
2778
2930
|
feedEl.style.transform = "";
|
|
2779
2931
|
feedEl.style.borderRadius = "";
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2932
|
+
chromeEls.forEach((el) => {
|
|
2933
|
+
el.style.opacity = "";
|
|
2934
|
+
el.style.transition = "";
|
|
2935
|
+
});
|
|
2783
2936
|
this._escHandler = (e) => {
|
|
2784
2937
|
if (e.key === "Escape") this.close();
|
|
2785
2938
|
};
|
|
@@ -2806,6 +2959,12 @@ class FeedView {
|
|
|
2806
2959
|
if (this.feedManager?.activeItemId && !canTransfer) {
|
|
2807
2960
|
this.feedManager._deactivateItem(this.feedManager.activeItemId);
|
|
2808
2961
|
}
|
|
2962
|
+
const targetItemId = canTransfer ? this._openItemId : activeItemId;
|
|
2963
|
+
if (targetItemId && this.feedManager) {
|
|
2964
|
+
const targetEl = this.feedManager.itemEls.get(targetItemId);
|
|
2965
|
+
if (targetEl) targetEl.scrollIntoView({ behavior: "instant", block: "start" });
|
|
2966
|
+
}
|
|
2967
|
+
const savedScrollTop = feedEl.scrollTop;
|
|
2809
2968
|
feedEl.style.position = "fixed";
|
|
2810
2969
|
feedEl.style.left = `${feedRect.left}px`;
|
|
2811
2970
|
feedEl.style.top = `${feedRect.top}px`;
|
|
@@ -2817,7 +2976,20 @@ class FeedView {
|
|
|
2817
2976
|
feedEl.style.aspectRatio = "unset";
|
|
2818
2977
|
feedEl.style.maxHeight = "none";
|
|
2819
2978
|
document.body.appendChild(feedEl);
|
|
2979
|
+
feedEl.scrollTop = savedScrollTop;
|
|
2820
2980
|
this.overlayEl.classList.remove("skw-active", "skw-feed-ready");
|
|
2981
|
+
let thumbOverlay = null;
|
|
2982
|
+
if (this._openThumbnailUrl) {
|
|
2983
|
+
const targetItemId2 = canTransfer ? this._openItemId : activeItemId;
|
|
2984
|
+
const targetEl = targetItemId2 && this.feedManager?.itemEls.get(targetItemId2);
|
|
2985
|
+
const videoContainer = targetEl?.querySelector('[data-ref="videoContainer"]');
|
|
2986
|
+
if (videoContainer) {
|
|
2987
|
+
thumbOverlay = document.createElement("img");
|
|
2988
|
+
thumbOverlay.src = this._openThumbnailUrl;
|
|
2989
|
+
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;";
|
|
2990
|
+
videoContainer.appendChild(thumbOverlay);
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2821
2993
|
const slotRadius = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--skw-radius").trim()) || 12;
|
|
2822
2994
|
const scaleX = targetSlotRect.width / feedRect.width;
|
|
2823
2995
|
const scaleY = targetSlotRect.height / feedRect.height;
|
|
@@ -2827,13 +2999,16 @@ class FeedView {
|
|
|
2827
2999
|
feedEl.style.transformOrigin = "0 0";
|
|
2828
3000
|
feedEl.style.overflow = "hidden";
|
|
2829
3001
|
feedEl.style.scrollSnapType = "none";
|
|
3002
|
+
feedEl.style.pointerEvents = "none";
|
|
2830
3003
|
feedEl.getBoundingClientRect();
|
|
2831
3004
|
feedEl.classList.add("skw-flip-animating");
|
|
2832
3005
|
requestAnimationFrame(() => {
|
|
2833
3006
|
feedEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
2834
3007
|
feedEl.style.borderRadius = `${endRadius}px`;
|
|
3008
|
+
if (thumbOverlay) thumbOverlay.style.opacity = "1";
|
|
2835
3009
|
});
|
|
2836
3010
|
await this._waitForTransitionEnd(feedEl, 450);
|
|
3011
|
+
if (thumbOverlay) thumbOverlay.remove();
|
|
2837
3012
|
let transferVideo = null;
|
|
2838
3013
|
let transferHls = null;
|
|
2839
3014
|
if (canTransfer) {
|
|
@@ -2858,6 +3033,7 @@ class FeedView {
|
|
|
2858
3033
|
feedEl.style.transformOrigin = "";
|
|
2859
3034
|
feedEl.style.overflow = "";
|
|
2860
3035
|
feedEl.style.scrollSnapType = "";
|
|
3036
|
+
feedEl.style.pointerEvents = "";
|
|
2861
3037
|
feedEl.style.transform = "";
|
|
2862
3038
|
feedEl.style.borderRadius = "";
|
|
2863
3039
|
feedWrapper.insertBefore(feedEl, feedWrapper.firstChild);
|
|
@@ -2987,11 +3163,20 @@ class WidgetPlayerPool {
|
|
|
2987
3163
|
}
|
|
2988
3164
|
promoteToActive(itemId) {
|
|
2989
3165
|
const hls = this.hlsInstances.get(itemId);
|
|
2990
|
-
if (hls)
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
3166
|
+
if (!hls) return;
|
|
3167
|
+
hls.config.maxBufferLength = WidgetPlayerPool.ACTIVE_HLS_CONFIG.maxBufferLength;
|
|
3168
|
+
hls.config.maxMaxBufferLength = WidgetPlayerPool.ACTIVE_HLS_CONFIG.maxMaxBufferLength;
|
|
3169
|
+
hls.autoLevelCapping = -1;
|
|
3170
|
+
const top = hls.levels ? hls.levels.length - 1 : -1;
|
|
3171
|
+
if (top > 0 && hls.currentLevel < top) {
|
|
3172
|
+
hls.currentLevel = top;
|
|
3173
|
+
const player = this.assignments.get(itemId);
|
|
3174
|
+
if (player) {
|
|
3175
|
+
player.currentTime = player.currentTime;
|
|
3176
|
+
}
|
|
3177
|
+
setTimeout(() => {
|
|
3178
|
+
if (!hls.destroyed) hls.currentLevel = -1;
|
|
3179
|
+
}, 4e3);
|
|
2995
3180
|
}
|
|
2996
3181
|
}
|
|
2997
3182
|
_destroyHls(itemId) {
|
|
@@ -3596,7 +3781,7 @@ const CSS = `
|
|
|
3596
3781
|
|
|
3597
3782
|
/* Video container */
|
|
3598
3783
|
.sk-video-container{position:absolute;inset:0;width:100%;height:100%;overflow:hidden;background-size:cover;background-position:center}
|
|
3599
|
-
.sk-video-container video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .
|
|
3784
|
+
.sk-video-container video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .35s ease}
|
|
3600
3785
|
|
|
3601
3786
|
/* Tap zone */
|
|
3602
3787
|
.sk-tap-zone{position:absolute;inset:0;z-index:3;cursor:pointer}
|
|
@@ -3612,7 +3797,7 @@ const CSS = `
|
|
|
3612
3797
|
|
|
3613
3798
|
/* Widget slot */
|
|
3614
3799
|
.skw-slot{position:relative;overflow:hidden;cursor:pointer}
|
|
3615
|
-
.skw-slot video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .
|
|
3800
|
+
.skw-slot video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s ease}
|
|
3616
3801
|
.skw-slot-thumb{position:absolute;inset:0;background-size:cover;background-position:center}
|
|
3617
3802
|
.skw-slot-overlay{position:absolute;inset:0;z-index:4;pointer-events:none}
|
|
3618
3803
|
.skw-slot-overlay>*{pointer-events:auto}
|