@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/cli.cjs
CHANGED
|
@@ -3071,49 +3071,146 @@ function generateLrsBridgeCode(options) {
|
|
|
3071
3071
|
function setupMediaInterceptors() {
|
|
3072
3072
|
if (!TRACK_MEDIA) return;
|
|
3073
3073
|
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3074
|
+
// Track which elements we've already attached listeners to
|
|
3075
|
+
var trackedMedia = new WeakSet();
|
|
3076
|
+
|
|
3077
|
+
// Helper to get media name/title from element or surrounding context
|
|
3078
|
+
function getMediaName(el) {
|
|
3079
|
+
// Check element attributes
|
|
3080
|
+
var name = el.title || el.getAttribute('aria-label') || el.getAttribute('data-name');
|
|
3081
|
+
if (name) return name;
|
|
3082
|
+
|
|
3083
|
+
// Check parent Rise video block for title
|
|
3084
|
+
var videoBlock = findClosest(el, '[data-block-type="video"], .blocks-video, .video-block');
|
|
3085
|
+
if (videoBlock) {
|
|
3086
|
+
var titleEl = videoBlock.querySelector('.video-title, .block-title, [class*="title"]');
|
|
3087
|
+
if (titleEl) return titleEl.textContent.trim();
|
|
3088
|
+
}
|
|
3089
|
+
|
|
3090
|
+
// Use src filename as fallback
|
|
3091
|
+
var src = el.src || el.currentSrc || '';
|
|
3092
|
+
if (src) {
|
|
3093
|
+
var filename = src.split('/').pop().split('?')[0];
|
|
3094
|
+
if (filename && filename.length < 100) return filename;
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
return el.tagName.toLowerCase();
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
// Attach media event listeners to a single element
|
|
3101
|
+
function attachMediaListeners(el) {
|
|
3102
|
+
if (trackedMedia.has(el)) return;
|
|
3103
|
+
trackedMedia.add(el);
|
|
3104
|
+
|
|
3105
|
+
var mediaType = el.tagName.toLowerCase();
|
|
3106
|
+
log('Attaching media listeners to:', mediaType, el.src || el.currentSrc || 'no-src');
|
|
3107
|
+
|
|
3108
|
+
el.addEventListener('play', function() {
|
|
3109
|
+
log('Media play event captured:', mediaType);
|
|
3077
3110
|
LRS.mediaPlayed({
|
|
3078
|
-
type:
|
|
3079
|
-
src:
|
|
3080
|
-
name:
|
|
3081
|
-
currentTime:
|
|
3082
|
-
duration:
|
|
3111
|
+
type: mediaType,
|
|
3112
|
+
src: el.src || el.currentSrc || '',
|
|
3113
|
+
name: getMediaName(el),
|
|
3114
|
+
currentTime: el.currentTime || 0,
|
|
3115
|
+
duration: el.duration || 0,
|
|
3083
3116
|
action: 'play'
|
|
3084
3117
|
});
|
|
3085
|
-
}
|
|
3086
|
-
}, true);
|
|
3118
|
+
});
|
|
3087
3119
|
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3120
|
+
el.addEventListener('pause', function() {
|
|
3121
|
+
// Ignore pause events that fire right before ended
|
|
3122
|
+
if (el.ended) return;
|
|
3123
|
+
log('Media pause event captured:', mediaType);
|
|
3091
3124
|
LRS.mediaPlayed({
|
|
3092
|
-
type:
|
|
3093
|
-
src:
|
|
3094
|
-
name:
|
|
3095
|
-
currentTime:
|
|
3096
|
-
duration:
|
|
3125
|
+
type: mediaType,
|
|
3126
|
+
src: el.src || el.currentSrc || '',
|
|
3127
|
+
name: getMediaName(el),
|
|
3128
|
+
currentTime: el.currentTime || 0,
|
|
3129
|
+
duration: el.duration || 0,
|
|
3097
3130
|
action: 'pause'
|
|
3098
3131
|
});
|
|
3099
|
-
}
|
|
3100
|
-
}, true);
|
|
3132
|
+
});
|
|
3101
3133
|
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
|
|
3134
|
+
el.addEventListener('ended', function() {
|
|
3135
|
+
log('Media ended event captured:', mediaType);
|
|
3105
3136
|
LRS.mediaPlayed({
|
|
3106
|
-
type:
|
|
3107
|
-
src:
|
|
3108
|
-
name:
|
|
3109
|
-
currentTime:
|
|
3110
|
-
duration:
|
|
3137
|
+
type: mediaType,
|
|
3138
|
+
src: el.src || el.currentSrc || '',
|
|
3139
|
+
name: getMediaName(el),
|
|
3140
|
+
currentTime: el.duration || 0,
|
|
3141
|
+
duration: el.duration || 0,
|
|
3111
3142
|
action: 'completed'
|
|
3112
3143
|
});
|
|
3144
|
+
});
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
// Scan for and attach listeners to all video/audio elements
|
|
3148
|
+
function scanForMedia(root) {
|
|
3149
|
+
var elements = (root || document).querySelectorAll('video, audio');
|
|
3150
|
+
log('Scanning for media elements, found:', elements.length);
|
|
3151
|
+
for (var i = 0; i < elements.length; i++) {
|
|
3152
|
+
attachMediaListeners(elements[i]);
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
// Initial scan
|
|
3157
|
+
scanForMedia();
|
|
3158
|
+
|
|
3159
|
+
// Document-level capture for any we might miss
|
|
3160
|
+
document.addEventListener('play', function(e) {
|
|
3161
|
+
var target = e.target;
|
|
3162
|
+
if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
|
|
3163
|
+
// Attach listeners if not already tracked
|
|
3164
|
+
if (!trackedMedia.has(target)) {
|
|
3165
|
+
log('Captured play from untracked media, attaching listeners');
|
|
3166
|
+
attachMediaListeners(target);
|
|
3167
|
+
}
|
|
3113
3168
|
}
|
|
3114
3169
|
}, true);
|
|
3115
3170
|
|
|
3116
|
-
|
|
3171
|
+
// MutationObserver to detect dynamically added video/audio elements
|
|
3172
|
+
var mediaObserver = new MutationObserver(function(mutations) {
|
|
3173
|
+
var needsScan = false;
|
|
3174
|
+
mutations.forEach(function(mutation) {
|
|
3175
|
+
mutation.addedNodes.forEach(function(node) {
|
|
3176
|
+
if (node.nodeType === 1) {
|
|
3177
|
+
if (node.tagName === 'VIDEO' || node.tagName === 'AUDIO') {
|
|
3178
|
+
attachMediaListeners(node);
|
|
3179
|
+
} else if (node.querySelectorAll) {
|
|
3180
|
+
// Check for nested video/audio
|
|
3181
|
+
var nested = node.querySelectorAll('video, audio');
|
|
3182
|
+
if (nested.length > 0) {
|
|
3183
|
+
needsScan = true;
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
});
|
|
3188
|
+
});
|
|
3189
|
+
if (needsScan) {
|
|
3190
|
+
scanForMedia();
|
|
3191
|
+
}
|
|
3192
|
+
});
|
|
3193
|
+
|
|
3194
|
+
// Start observing once DOM is ready
|
|
3195
|
+
function startMediaObserver() {
|
|
3196
|
+
if (document.body) {
|
|
3197
|
+
mediaObserver.observe(document.body, {
|
|
3198
|
+
childList: true,
|
|
3199
|
+
subtree: true
|
|
3200
|
+
});
|
|
3201
|
+
log('Media mutation observer started');
|
|
3202
|
+
} else {
|
|
3203
|
+
setTimeout(startMediaObserver, 100);
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
startMediaObserver();
|
|
3207
|
+
|
|
3208
|
+
// Periodic rescan for Rise lazy-loaded content
|
|
3209
|
+
setInterval(function() {
|
|
3210
|
+
scanForMedia();
|
|
3211
|
+
}, 3000);
|
|
3212
|
+
|
|
3213
|
+
log('Media interceptors set up (enhanced)');
|
|
3117
3214
|
}
|
|
3118
3215
|
|
|
3119
3216
|
function setupNavigationInterceptors() {
|
|
@@ -3354,7 +3451,7 @@ function generateLrsBridgeCode(options) {
|
|
|
3354
3451
|
// ========================================================================
|
|
3355
3452
|
|
|
3356
3453
|
function init() {
|
|
3357
|
-
log('Initializing LRS bridge v2.
|
|
3454
|
+
log('Initializing LRS bridge v2.3.0...');
|
|
3358
3455
|
|
|
3359
3456
|
// Extract course info early
|
|
3360
3457
|
extractCourseInfo();
|