@patch-adams/core 1.4.2 → 1.4.3
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/cli.cjs +127 -30
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +127 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +127 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +127 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2735,49 +2735,146 @@ function generateLrsBridgeCode(options) {
|
|
|
2735
2735
|
function setupMediaInterceptors() {
|
|
2736
2736
|
if (!TRACK_MEDIA) return;
|
|
2737
2737
|
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2738
|
+
// Track which elements we've already attached listeners to
|
|
2739
|
+
var trackedMedia = new WeakSet();
|
|
2740
|
+
|
|
2741
|
+
// Helper to get media name/title from element or surrounding context
|
|
2742
|
+
function getMediaName(el) {
|
|
2743
|
+
// Check element attributes
|
|
2744
|
+
var name = el.title || el.getAttribute('aria-label') || el.getAttribute('data-name');
|
|
2745
|
+
if (name) return name;
|
|
2746
|
+
|
|
2747
|
+
// Check parent Rise video block for title
|
|
2748
|
+
var videoBlock = findClosest(el, '[data-block-type="video"], .blocks-video, .video-block');
|
|
2749
|
+
if (videoBlock) {
|
|
2750
|
+
var titleEl = videoBlock.querySelector('.video-title, .block-title, [class*="title"]');
|
|
2751
|
+
if (titleEl) return titleEl.textContent.trim();
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
// Use src filename as fallback
|
|
2755
|
+
var src = el.src || el.currentSrc || '';
|
|
2756
|
+
if (src) {
|
|
2757
|
+
var filename = src.split('/').pop().split('?')[0];
|
|
2758
|
+
if (filename && filename.length < 100) return filename;
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
return el.tagName.toLowerCase();
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
// Attach media event listeners to a single element
|
|
2765
|
+
function attachMediaListeners(el) {
|
|
2766
|
+
if (trackedMedia.has(el)) return;
|
|
2767
|
+
trackedMedia.add(el);
|
|
2768
|
+
|
|
2769
|
+
var mediaType = el.tagName.toLowerCase();
|
|
2770
|
+
log('Attaching media listeners to:', mediaType, el.src || el.currentSrc || 'no-src');
|
|
2771
|
+
|
|
2772
|
+
el.addEventListener('play', function() {
|
|
2773
|
+
log('Media play event captured:', mediaType);
|
|
2741
2774
|
LRS.mediaPlayed({
|
|
2742
|
-
type:
|
|
2743
|
-
src:
|
|
2744
|
-
name:
|
|
2745
|
-
currentTime:
|
|
2746
|
-
duration:
|
|
2775
|
+
type: mediaType,
|
|
2776
|
+
src: el.src || el.currentSrc || '',
|
|
2777
|
+
name: getMediaName(el),
|
|
2778
|
+
currentTime: el.currentTime || 0,
|
|
2779
|
+
duration: el.duration || 0,
|
|
2747
2780
|
action: 'play'
|
|
2748
2781
|
});
|
|
2749
|
-
}
|
|
2750
|
-
}, true);
|
|
2782
|
+
});
|
|
2751
2783
|
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2784
|
+
el.addEventListener('pause', function() {
|
|
2785
|
+
// Ignore pause events that fire right before ended
|
|
2786
|
+
if (el.ended) return;
|
|
2787
|
+
log('Media pause event captured:', mediaType);
|
|
2755
2788
|
LRS.mediaPlayed({
|
|
2756
|
-
type:
|
|
2757
|
-
src:
|
|
2758
|
-
name:
|
|
2759
|
-
currentTime:
|
|
2760
|
-
duration:
|
|
2789
|
+
type: mediaType,
|
|
2790
|
+
src: el.src || el.currentSrc || '',
|
|
2791
|
+
name: getMediaName(el),
|
|
2792
|
+
currentTime: el.currentTime || 0,
|
|
2793
|
+
duration: el.duration || 0,
|
|
2761
2794
|
action: 'pause'
|
|
2762
2795
|
});
|
|
2763
|
-
}
|
|
2764
|
-
}, true);
|
|
2796
|
+
});
|
|
2765
2797
|
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
|
|
2798
|
+
el.addEventListener('ended', function() {
|
|
2799
|
+
log('Media ended event captured:', mediaType);
|
|
2769
2800
|
LRS.mediaPlayed({
|
|
2770
|
-
type:
|
|
2771
|
-
src:
|
|
2772
|
-
name:
|
|
2773
|
-
currentTime:
|
|
2774
|
-
duration:
|
|
2801
|
+
type: mediaType,
|
|
2802
|
+
src: el.src || el.currentSrc || '',
|
|
2803
|
+
name: getMediaName(el),
|
|
2804
|
+
currentTime: el.duration || 0,
|
|
2805
|
+
duration: el.duration || 0,
|
|
2775
2806
|
action: 'completed'
|
|
2776
2807
|
});
|
|
2808
|
+
});
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
// Scan for and attach listeners to all video/audio elements
|
|
2812
|
+
function scanForMedia(root) {
|
|
2813
|
+
var elements = (root || document).querySelectorAll('video, audio');
|
|
2814
|
+
log('Scanning for media elements, found:', elements.length);
|
|
2815
|
+
for (var i = 0; i < elements.length; i++) {
|
|
2816
|
+
attachMediaListeners(elements[i]);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
// Initial scan
|
|
2821
|
+
scanForMedia();
|
|
2822
|
+
|
|
2823
|
+
// Document-level capture for any we might miss
|
|
2824
|
+
document.addEventListener('play', function(e) {
|
|
2825
|
+
var target = e.target;
|
|
2826
|
+
if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
|
|
2827
|
+
// Attach listeners if not already tracked
|
|
2828
|
+
if (!trackedMedia.has(target)) {
|
|
2829
|
+
log('Captured play from untracked media, attaching listeners');
|
|
2830
|
+
attachMediaListeners(target);
|
|
2831
|
+
}
|
|
2777
2832
|
}
|
|
2778
2833
|
}, true);
|
|
2779
2834
|
|
|
2780
|
-
|
|
2835
|
+
// MutationObserver to detect dynamically added video/audio elements
|
|
2836
|
+
var mediaObserver = new MutationObserver(function(mutations) {
|
|
2837
|
+
var needsScan = false;
|
|
2838
|
+
mutations.forEach(function(mutation) {
|
|
2839
|
+
mutation.addedNodes.forEach(function(node) {
|
|
2840
|
+
if (node.nodeType === 1) {
|
|
2841
|
+
if (node.tagName === 'VIDEO' || node.tagName === 'AUDIO') {
|
|
2842
|
+
attachMediaListeners(node);
|
|
2843
|
+
} else if (node.querySelectorAll) {
|
|
2844
|
+
// Check for nested video/audio
|
|
2845
|
+
var nested = node.querySelectorAll('video, audio');
|
|
2846
|
+
if (nested.length > 0) {
|
|
2847
|
+
needsScan = true;
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
});
|
|
2852
|
+
});
|
|
2853
|
+
if (needsScan) {
|
|
2854
|
+
scanForMedia();
|
|
2855
|
+
}
|
|
2856
|
+
});
|
|
2857
|
+
|
|
2858
|
+
// Start observing once DOM is ready
|
|
2859
|
+
function startMediaObserver() {
|
|
2860
|
+
if (document.body) {
|
|
2861
|
+
mediaObserver.observe(document.body, {
|
|
2862
|
+
childList: true,
|
|
2863
|
+
subtree: true
|
|
2864
|
+
});
|
|
2865
|
+
log('Media mutation observer started');
|
|
2866
|
+
} else {
|
|
2867
|
+
setTimeout(startMediaObserver, 100);
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
startMediaObserver();
|
|
2871
|
+
|
|
2872
|
+
// Periodic rescan for Rise lazy-loaded content
|
|
2873
|
+
setInterval(function() {
|
|
2874
|
+
scanForMedia();
|
|
2875
|
+
}, 3000);
|
|
2876
|
+
|
|
2877
|
+
log('Media interceptors set up (enhanced)');
|
|
2781
2878
|
}
|
|
2782
2879
|
|
|
2783
2880
|
function setupNavigationInterceptors() {
|
|
@@ -3018,7 +3115,7 @@ function generateLrsBridgeCode(options) {
|
|
|
3018
3115
|
// ========================================================================
|
|
3019
3116
|
|
|
3020
3117
|
function init() {
|
|
3021
|
-
log('Initializing LRS bridge v2.
|
|
3118
|
+
log('Initializing LRS bridge v2.3.0...');
|
|
3022
3119
|
|
|
3023
3120
|
// Extract course info early
|
|
3024
3121
|
extractCourseInfo();
|