Skip to content

Commit 7fd9c3a

Browse files
authored
Merge pull request #2148 from rtCamp/develop
Version update v4.7.0 [ master ]
2 parents fac2432 + 781c25d commit 7fd9c3a

File tree

12 files changed

+760
-43
lines changed

12 files changed

+760
-43
lines changed

Gruntfile.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ module.exports = function (grunt) {
6262
files: {
6363
'app/assets/admin/js/admin.min.js': ['app/assets/admin/js/scripts.js']
6464
}
65+
},
66+
godam: {
67+
files: {
68+
'app/assets/js/godam-integration.min.js': ['app/assets/js/godam-integration.js']
69+
}
70+
},
71+
godam_ajax_refresh: {
72+
files: {
73+
'app/assets/js/godam-ajax-refresh.min.js': ['app/assets/js/godam-ajax-refresh.js']
74+
}
6575
}
6676
}
6777
});

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ https://www.youtube.com/watch?v=dJrykKQGDcs
151151

152152
## Changelog ##
153153

154+
### 4.7.0
155+
156+
* ENHANCEMENTS
157+
* Added integration with GoDAM plugin's video player.
158+
* Enabled support for GoDAM video player in rtMedia media gallery, BuddyPress activity stream, groups, and forums.
159+
* Improved handling of player enqueue conditions based on GoDAM plugin status.
160+
* Refined script loading to ensure compatibility across WordPress, BuddyPress, and rtMedia components.
161+
162+
* FIXED
163+
* Prevented conflicts with `mediaelement.js` when GoDAM plugin is active.
164+
* Deregistered conflicting scripts to ensure seamless fallback and prevent duplication in player initialization.
165+
154166
### 4.6.23
155167

156168
* Fixed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
// Enhanced AJAX function with better error handling and retry logic
2+
function refreshSingleComment(commentId, node) {
3+
// Validation checks
4+
if (!commentId || !node) {
5+
return;
6+
}
7+
8+
// Check if GodamAjax object exists
9+
if (typeof GodamAjax === 'undefined' || !GodamAjax.ajax_url || !GodamAjax.nonce) {
10+
return;
11+
}
12+
13+
// Check if node is still in the DOM
14+
if (!document.contains(node)) {
15+
return;
16+
}
17+
18+
// Prevent duplicate requests
19+
if (node.classList.contains('refreshing')) {
20+
return;
21+
}
22+
node.classList.add('refreshing');
23+
24+
// Create AbortController for timeout handling
25+
const controller = new AbortController();
26+
const timeoutId = setTimeout(() => {
27+
controller.abort();
28+
}, 15000); // 15 second timeout
29+
30+
fetch(GodamAjax.ajax_url, {
31+
method: 'POST',
32+
headers: {
33+
'Content-Type': 'application/x-www-form-urlencoded',
34+
},
35+
body: new URLSearchParams({
36+
action: 'get_single_activity_comment_html',
37+
comment_id: commentId,
38+
nonce: GodamAjax.nonce,
39+
}),
40+
signal: controller.signal
41+
})
42+
.then(response => {
43+
clearTimeout(timeoutId);
44+
45+
// Check if response is ok
46+
if (!response.ok) {
47+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
48+
}
49+
50+
// Check content type
51+
const contentType = response.headers.get('content-type');
52+
if (!contentType || !contentType.includes('application/json')) {
53+
throw new Error('Server returned non-JSON response');
54+
}
55+
56+
return response.json();
57+
})
58+
.then(data => {
59+
if (data && data.success && data.data && data.data.html) {
60+
// Success - handle the response
61+
handleSuccessfulResponse(data, commentId, node);
62+
} else {
63+
// AJAX returned error
64+
const errorMsg = data && data.data ? data.data : 'Unknown AJAX error';
65+
console.error('AJAX error:', errorMsg);
66+
67+
// Optional: Retry once after a delay
68+
setTimeout(() => {
69+
retryRefreshComment(commentId, node, 1);
70+
}, 2000);
71+
}
72+
})
73+
.catch(error => {
74+
clearTimeout(timeoutId);
75+
console.error('Fetch error:', error);
76+
77+
// Handle specific error types
78+
if (error.name === 'AbortError') {
79+
console.error('Request timed out');
80+
} else if (error.message.includes('Failed to fetch')) {
81+
console.error('Network error - possible connectivity issue');
82+
// Retry after network error
83+
setTimeout(() => {
84+
retryRefreshComment(commentId, node, 1);
85+
}, 3000);
86+
}
87+
})
88+
.finally(() => {
89+
clearTimeout(timeoutId);
90+
// Always remove refreshing class
91+
if (document.contains(node)) {
92+
node.classList.remove('refreshing');
93+
}
94+
});
95+
}
96+
97+
// Retry function with exponential backoff
98+
function retryRefreshComment(commentId, node, attempt = 1) {
99+
const maxRetries = 2;
100+
101+
if (attempt > maxRetries) {
102+
console.error(`Failed to refresh comment ${commentId} after ${maxRetries} retries`);
103+
return;
104+
}
105+
106+
// Check if node still exists
107+
if (!document.contains(node)) {
108+
return;
109+
}
110+
111+
// Exponential backoff delay
112+
const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s...
113+
114+
setTimeout(() => {
115+
// Remove any existing refreshing class
116+
node.classList.remove('refreshing');
117+
118+
// Try again with modified fetch (more conservative approach)
119+
fetch(GodamAjax.ajax_url, {
120+
method: 'POST',
121+
headers: {
122+
'Content-Type': 'application/x-www-form-urlencoded',
123+
'Cache-Control': 'no-cache',
124+
},
125+
body: new URLSearchParams({
126+
action: 'get_single_activity_comment_html',
127+
comment_id: commentId,
128+
nonce: GodamAjax.nonce,
129+
retry: attempt.toString()
130+
}),
131+
})
132+
.then(response => response.json())
133+
.then(data => {
134+
if (data && data.success && data.data && data.data.html) {
135+
handleSuccessfulResponse(data, commentId, node);
136+
} else {
137+
// Retry again if not max attempts
138+
if (attempt < maxRetries) {
139+
retryRefreshComment(commentId, node, attempt + 1);
140+
}
141+
}
142+
})
143+
.catch(error => {
144+
console.error(`Retry ${attempt} failed:`, error);
145+
if (attempt < maxRetries) {
146+
retryRefreshComment(commentId, node, attempt + 1);
147+
}
148+
});
149+
}, delay);
150+
}
151+
152+
// Handle successful AJAX response
153+
function handleSuccessfulResponse(data, commentId, node) {
154+
try {
155+
// Find parent activity more safely
156+
const activityItem = node.closest('.activity-item');
157+
if (!activityItem) {
158+
console.error('Could not find parent activity item');
159+
return;
160+
}
161+
162+
const parentActivityId = activityItem.id.replace('activity-', '');
163+
164+
// Locate comment container
165+
let commentList = document.querySelector(`#activity-${parentActivityId} .activity-comments`);
166+
if (!commentList) {
167+
commentList = document.createElement('ul');
168+
commentList.classList.add('activity-comments');
169+
activityItem.appendChild(commentList);
170+
}
171+
172+
// Create temporary container for HTML parsing
173+
const tempDiv = document.createElement('div');
174+
tempDiv.innerHTML = data.data.html.trim();
175+
const newCommentNode = tempDiv.firstElementChild;
176+
177+
if (newCommentNode) {
178+
// Insert new comment
179+
commentList.appendChild(newCommentNode);
180+
181+
// Remove old node safely
182+
if (node.parentNode && document.contains(node)) {
183+
node.parentNode.removeChild(node);
184+
}
185+
186+
// Initialize GODAMPlayer if available
187+
if (typeof GODAMPlayer === 'function') {
188+
try {
189+
GODAMPlayer(newCommentNode);
190+
} catch (playerError) {
191+
console.error('GODAMPlayer initialization failed:', playerError);
192+
}
193+
}
194+
195+
// Dispatch custom event for other scripts
196+
document.dispatchEvent(new CustomEvent('commentRefreshed', {
197+
detail: { commentId, node: newCommentNode }
198+
}));
199+
200+
} else {
201+
console.error('No valid comment node found in response HTML');
202+
}
203+
} catch (error) {
204+
console.error('Error handling successful response:', error);
205+
}
206+
}
207+
208+
// Enhanced DOM observer with debouncing
209+
document.addEventListener('DOMContentLoaded', () => {
210+
const commentsContainers = document.querySelectorAll('.activity-comments');
211+
212+
if (commentsContainers.length === 0) {
213+
return;
214+
}
215+
216+
// Debounce function to prevent rapid-fire calls
217+
function debounce(func, wait) {
218+
let timeout;
219+
return function executedFunction(...args) {
220+
const later = () => {
221+
clearTimeout(timeout);
222+
func(...args);
223+
};
224+
clearTimeout(timeout);
225+
timeout = setTimeout(later, wait);
226+
};
227+
}
228+
229+
commentsContainers.forEach((container) => {
230+
// Initialize GODAMPlayer on existing comments
231+
if (typeof GODAMPlayer === 'function') {
232+
try {
233+
GODAMPlayer(container);
234+
} catch (error) {
235+
console.error('GODAMPlayer initialization failed:', error);
236+
}
237+
}
238+
239+
// Debounced mutation handler
240+
const debouncedHandler = debounce((mutations) => {
241+
mutations.forEach((mutation) => {
242+
mutation.addedNodes.forEach((node) => {
243+
if (node.nodeType === 1 && node.matches && node.matches('li[id^="acomment-"]')) {
244+
// Initialize GODAMPlayer first
245+
if (typeof GODAMPlayer === 'function') {
246+
try {
247+
GODAMPlayer(node);
248+
} catch (error) {
249+
console.error('GODAMPlayer initialization failed:', error);
250+
}
251+
}
252+
253+
// Extract comment ID and refresh with delay
254+
const commentId = node.id.replace('acomment-', '');
255+
256+
// Add longer delay to ensure DOM stability
257+
setTimeout(() => {
258+
if (document.contains(node)) {
259+
refreshSingleComment(commentId, node);
260+
}
261+
}, 250);
262+
}
263+
});
264+
});
265+
}, 100); // 100ms debounce
266+
267+
// Create observer
268+
const observer = new MutationObserver(debouncedHandler);
269+
270+
observer.observe(container, {
271+
childList: true,
272+
subtree: true
273+
});
274+
});
275+
});

app/assets/js/godam-ajax-refresh.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)