@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 CHANGED
@@ -3071,49 +3071,146 @@ function generateLrsBridgeCode(options) {
3071
3071
  function setupMediaInterceptors() {
3072
3072
  if (!TRACK_MEDIA) return;
3073
3073
 
3074
- document.addEventListener('play', function(e) {
3075
- var target = e.target;
3076
- if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
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: target.tagName.toLowerCase(),
3079
- src: target.src || target.currentSrc || '',
3080
- name: target.title || target.getAttribute('aria-label') || '',
3081
- currentTime: target.currentTime || 0,
3082
- duration: target.duration || 0,
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
- document.addEventListener('pause', function(e) {
3089
- var target = e.target;
3090
- if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
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: target.tagName.toLowerCase(),
3093
- src: target.src || target.currentSrc || '',
3094
- name: target.title || target.getAttribute('aria-label') || '',
3095
- currentTime: target.currentTime || 0,
3096
- duration: target.duration || 0,
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
- document.addEventListener('ended', function(e) {
3103
- var target = e.target;
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: target.tagName.toLowerCase(),
3107
- src: target.src || target.currentSrc || '',
3108
- name: target.title || target.getAttribute('aria-label') || '',
3109
- currentTime: target.duration || 0,
3110
- duration: target.duration || 0,
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
- log('Media interceptors set up');
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.2.0...');
3454
+ log('Initializing LRS bridge v2.3.0...');
3358
3455
 
3359
3456
  // Extract course info early
3360
3457
  extractCourseInfo();