nodebb-plugin-chat-search 0.0.3 → 0.0.4
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/library.js +49 -46
- package/package.json +1 -1
- package/static/lib/main.js +119 -117
package/library.js
CHANGED
|
@@ -18,22 +18,17 @@ plugin.addClientScript = async (scripts) => {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
async function searchGlobal(socket, data) {
|
|
21
|
-
if (!socket.uid)
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
21
|
+
if (!socket.uid) throw new Error('Not logged in');
|
|
22
|
+
|
|
25
23
|
let targetUid = socket.uid;
|
|
26
24
|
if (data.targetUid && parseInt(data.targetUid, 10) !== parseInt(socket.uid, 10)) {
|
|
27
25
|
const isAdmin = await user.isAdministrator(socket.uid);
|
|
28
|
-
if (!isAdmin)
|
|
29
|
-
throw new Error('אין הרשאה.');
|
|
30
|
-
}
|
|
26
|
+
if (!isAdmin) throw new Error('אין הרשאה.');
|
|
31
27
|
targetUid = data.targetUid;
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
const query = data.query;
|
|
35
31
|
const roomIds = await db.getSortedSetRevRange('uid:' + targetUid + ':chat:rooms', 0, -1);
|
|
36
|
-
|
|
37
32
|
let allResults = [];
|
|
38
33
|
|
|
39
34
|
for (const roomId of roomIds) {
|
|
@@ -41,66 +36,74 @@ async function searchGlobal(socket, data) {
|
|
|
41
36
|
if (!inRoom) continue;
|
|
42
37
|
|
|
43
38
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
39
|
+
let start = 0;
|
|
40
|
+
const batchSize = 50;
|
|
41
|
+
let roomMatches = [];
|
|
42
|
+
let continueFetching = true;
|
|
43
|
+
|
|
44
|
+
while (continueFetching) {
|
|
45
|
+
const messages = await messaging.getMessages({
|
|
46
|
+
callerUid: socket.uid,
|
|
47
|
+
uid: targetUid,
|
|
48
|
+
roomId: roomId,
|
|
49
|
+
isNew: false,
|
|
50
|
+
start: start,
|
|
51
|
+
stop: start + batchSize - 1
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!messages || !Array.isArray(messages) || messages.length === 0) {
|
|
55
|
+
continueFetching = false;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const matches = messages.filter(msg =>
|
|
60
|
+
msg.content && msg.content.toLowerCase().includes(query.toLowerCase())
|
|
61
|
+
);
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
if (matches.length > 0) {
|
|
64
|
+
roomMatches = roomMatches.concat(matches);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (messages.length < batchSize) {
|
|
68
|
+
continueFetching = false;
|
|
69
|
+
} else {
|
|
70
|
+
start += batchSize;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (roomMatches.length > 0) {
|
|
75
|
+
const uids = await messaging.getUidsInRoom(roomId, 0, -1);
|
|
76
|
+
const usersData = await user.getUsersFields(uids, ['uid', 'username', 'picture', 'icon:text', 'icon:bgColor']);
|
|
65
77
|
const otherUsers = usersData.filter(u => parseInt(u.uid, 10) !== parseInt(targetUid, 10));
|
|
66
78
|
|
|
67
|
-
// --- לוגיקת הקיצור (2 שמות + ועוד X) ---
|
|
68
79
|
let displayName = '';
|
|
69
|
-
|
|
70
|
-
if (otherUsers.length
|
|
71
|
-
|
|
72
|
-
} else if (otherUsers.length <= 2) {
|
|
73
|
-
// אם יש 1 או 2, מציגים את כולם
|
|
74
|
-
displayName = otherUsers.map(u => u.username).join(', ');
|
|
75
|
-
} else {
|
|
76
|
-
// אם יש יותר מ-2, לוקחים את ה-2 הראשונים ומוסיפים את היתרה
|
|
80
|
+
if (otherUsers.length === 0) displayName = 'צ\'אט עצמי';
|
|
81
|
+
else if (otherUsers.length <= 2) displayName = otherUsers.map(u => u.username).join(', ');
|
|
82
|
+
else {
|
|
77
83
|
const firstTwo = otherUsers.slice(0, 2).map(u => u.username).join(', ');
|
|
78
84
|
const remaining = otherUsers.length - 2;
|
|
79
85
|
displayName = `${firstTwo} ועוד ${remaining} משתמשים`;
|
|
80
86
|
}
|
|
81
|
-
// ----------------------------------------
|
|
82
87
|
|
|
83
88
|
const roomData = await messaging.getRoomData(roomId);
|
|
84
|
-
// שם החדר: אם יש שם מוגדר לקבוצה - קח אותו, אחרת קח את השמות שיצרנו
|
|
85
89
|
let roomName = (roomData && roomData.roomName) || displayName;
|
|
86
90
|
|
|
87
|
-
|
|
91
|
+
roomMatches.forEach(m => {
|
|
88
92
|
if (!m.user || !m.user.username) {
|
|
89
93
|
const sender = usersData.find(u => parseInt(u.uid, 10) === parseInt(m.fromuid, 10));
|
|
90
|
-
m.user = sender || { username: 'Unknown' };
|
|
94
|
+
m.user = sender || { username: 'Unknown', 'icon:bgColor': '#aaa' };
|
|
91
95
|
}
|
|
92
96
|
m.roomName = roomName;
|
|
93
97
|
m.targetUid = targetUid;
|
|
94
|
-
|
|
98
|
+
m.participants = otherUsers;
|
|
95
99
|
});
|
|
96
100
|
|
|
97
|
-
allResults = allResults.concat(
|
|
101
|
+
allResults = allResults.concat(roomMatches);
|
|
98
102
|
}
|
|
99
|
-
} catch (err) {
|
|
100
|
-
console.error(`[Chat Search] Error in room ${roomId}: ${err.message}`);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.error(`[Chat Search] Error in room ${roomId}: ${err.message}`);
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
|
-
|
|
104
107
|
return allResults;
|
|
105
108
|
}
|
|
106
109
|
|
package/package.json
CHANGED
package/static/lib/main.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// מצב גלובלי לזיכרון בין מעברי דפים
|
|
4
3
|
window.chatSearchState = window.chatSearchState || {
|
|
5
4
|
query: '',
|
|
6
5
|
resultsHtml: '',
|
|
@@ -9,27 +8,16 @@ window.chatSearchState = window.chatSearchState || {
|
|
|
9
8
|
};
|
|
10
9
|
|
|
11
10
|
$(document).ready(function () {
|
|
12
|
-
console.log('[Chat Search] Loaded (Instant No-Flicker).');
|
|
13
|
-
|
|
14
11
|
let observer = null;
|
|
15
12
|
|
|
16
|
-
// האזנה למעבר דפים
|
|
17
|
-
$(window).on('action:ajaxify.start', function () {
|
|
18
|
-
// לפני שהדף מתחלף, ננסה לשמור את האלמנט בזיכרון אם נרצה להחזירו (אופציונלי)
|
|
19
|
-
// כרגע אנו מסתמכים על בנייה מחדש מהירה מאוד
|
|
20
|
-
});
|
|
21
|
-
|
|
22
13
|
$(window).on('action:ajaxify.end', function (ev, data) {
|
|
23
|
-
// אם יש observer ישן, ננתק אותו כדי לא להעמיס
|
|
24
14
|
if (observer) observer.disconnect();
|
|
25
|
-
|
|
26
15
|
const isChatUrl = data.url.match(/^(user\/[^\/]+\/)?chats/);
|
|
27
|
-
const isChatTemplate = data.template && data.template.name === 'chats';
|
|
16
|
+
const isChatTemplate = data.template && (data.template.name === 'chats' || data.template === 'chats');
|
|
28
17
|
|
|
29
18
|
if (isChatUrl || isChatTemplate) {
|
|
30
|
-
|
|
19
|
+
initSearchInjection();
|
|
31
20
|
} else {
|
|
32
|
-
// יציאה מאזור הצ'אטים - איפוס הזיכרון
|
|
33
21
|
window.chatSearchState = { query: '', resultsHtml: '', isOpen: false, lastScroll: 0 };
|
|
34
22
|
}
|
|
35
23
|
});
|
|
@@ -39,113 +27,110 @@ $(document).ready(function () {
|
|
|
39
27
|
handleScrollToMessage();
|
|
40
28
|
});
|
|
41
29
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
initFastInjection();
|
|
30
|
+
if (ajaxify.data.template && (ajaxify.data.template.name === 'chats' || ajaxify.data.template === 'chats')) {
|
|
31
|
+
initSearchInjection();
|
|
45
32
|
}
|
|
46
33
|
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
for(let mutation of mutationsList) {
|
|
57
|
-
if (mutation.type === 'childList') {
|
|
58
|
-
// אם נוספו אלמנטים לדף, נבדוק אם הסרגל הגיע
|
|
59
|
-
const container = findContainer();
|
|
60
|
-
if (container.length > 0 && container.find('#global-chat-search-container').length === 0) {
|
|
61
|
-
addGlobalSearchBar(container);
|
|
62
|
-
}
|
|
34
|
+
function initSearchInjection() {
|
|
35
|
+
if (!injectSearchBar()) {
|
|
36
|
+
const targetNode = document.body;
|
|
37
|
+
const config = { childList: true, subtree: true };
|
|
38
|
+
observer = new MutationObserver(function(mutationsList) {
|
|
39
|
+
const container = findContainer();
|
|
40
|
+
if (container.length > 0) {
|
|
41
|
+
injectSearchBar(container);
|
|
42
|
+
observer.disconnect();
|
|
63
43
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
observer.observe(targetNode, config);
|
|
68
|
-
|
|
69
|
-
// 3. גיבוי: Interval מהיר מאוד (50ms) למקרה שה-Observer פספס
|
|
70
|
-
let attempts = 0;
|
|
71
|
-
const interval = setInterval(() => {
|
|
72
|
-
attempts++;
|
|
73
|
-
if (tryInject()) {
|
|
74
|
-
// לא עוצרים את האינטרוול מיד, כי לפעמים NodeBB מרענן פעמיים
|
|
75
|
-
if (attempts > 20) clearInterval(interval);
|
|
76
|
-
} else if (attempts > 40) { // 2 שניות
|
|
77
|
-
clearInterval(interval);
|
|
78
|
-
}
|
|
79
|
-
}, 50);
|
|
44
|
+
});
|
|
45
|
+
observer.observe(targetNode, config);
|
|
46
|
+
}
|
|
80
47
|
}
|
|
81
48
|
|
|
82
49
|
function findContainer() {
|
|
83
|
-
// סדר עדיפויות למציאת הקונטיינר
|
|
84
50
|
let container = $('[component="chat/nav-wrapper"]');
|
|
85
51
|
if (container.length === 0) container = $('.chats-page').find('.col-md-4').first();
|
|
52
|
+
if (container.length === 0) container = $('[component="chat/list"]').parent();
|
|
86
53
|
return container;
|
|
87
54
|
}
|
|
88
55
|
|
|
89
|
-
function
|
|
90
|
-
const container = findContainer();
|
|
91
|
-
if (container.length
|
|
92
|
-
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
56
|
+
function injectSearchBar(containerElement) {
|
|
57
|
+
const container = containerElement || findContainer();
|
|
58
|
+
if (container.length === 0) return false;
|
|
59
|
+
if ($('#global-chat-search-container').length > 0) return true;
|
|
97
60
|
|
|
98
|
-
function addGlobalSearchBar(container) {
|
|
99
|
-
if ($('#global-chat-search-container').length > 0) return;
|
|
100
|
-
|
|
101
|
-
// ה-HTML של התיבה
|
|
102
61
|
const searchHtml = `
|
|
103
|
-
<div id="global-chat-search-container" style="padding: 10px; background: #fff; border-bottom: 1px solid #ddd; margin-bottom:
|
|
62
|
+
<div id="global-chat-search-container" style="padding: 10px; background: #fff; border-bottom: 1px solid #ddd; margin-bottom: 5px;">
|
|
104
63
|
<div class="input-group">
|
|
105
64
|
<input type="text" id="global-chat-search" class="form-control" placeholder="חפש הודעה..." style="font-size: 14px; height: 34px;">
|
|
106
65
|
<span class="input-group-btn">
|
|
107
66
|
<button class="btn btn-primary" id="btn-chat-search" type="button" style="height: 34px;"><i class="fa fa-search"></i></button>
|
|
108
67
|
</span>
|
|
109
68
|
</div>
|
|
110
|
-
<div id="global-search-results" style="margin-top: 5px; max-height: 400px;
|
|
69
|
+
<div id="global-search-results" class="chats-list overflow-auto ghost-scrollbar" style="margin-top: 5px; max-height: 400px; display:none;"></div>
|
|
111
70
|
</div>
|
|
112
71
|
`;
|
|
113
72
|
|
|
114
73
|
container.prepend(searchHtml);
|
|
115
|
-
|
|
116
|
-
|
|
74
|
+
restoreState();
|
|
75
|
+
attachEvents();
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function attachEvents() {
|
|
80
|
+
$('#btn-chat-search').off('click').on('click', executeSearch);
|
|
81
|
+
const input = $('#global-chat-search');
|
|
82
|
+
input.off('keypress').on('keypress', function (e) {
|
|
83
|
+
if (e.which === 13) executeSearch();
|
|
84
|
+
});
|
|
85
|
+
input.on('input', function() {
|
|
86
|
+
window.chatSearchState.query = $(this).val();
|
|
87
|
+
});
|
|
88
|
+
$('#global-search-results').on('scroll', function() {
|
|
89
|
+
window.chatSearchState.lastScroll = $(this).scrollTop();
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function restoreState() {
|
|
117
94
|
const input = $('#global-chat-search');
|
|
118
95
|
const results = $('#global-search-results');
|
|
119
|
-
|
|
120
|
-
if (window.chatSearchState.query) {
|
|
121
|
-
input.val(window.chatSearchState.query);
|
|
122
|
-
}
|
|
123
|
-
|
|
96
|
+
if (window.chatSearchState.query) input.val(window.chatSearchState.query);
|
|
124
97
|
if (window.chatSearchState.isOpen && window.chatSearchState.resultsHtml) {
|
|
125
98
|
results.html(window.chatSearchState.resultsHtml).show();
|
|
126
|
-
|
|
127
|
-
if (window.chatSearchState.lastScroll > 0)
|
|
128
|
-
results.scrollTop(window.chatSearchState.lastScroll);
|
|
129
|
-
}
|
|
99
|
+
if ($.fn.timeago) results.find('.timeago').timeago();
|
|
100
|
+
if (window.chatSearchState.lastScroll > 0) results.scrollTop(window.chatSearchState.lastScroll);
|
|
130
101
|
highlightActiveChat();
|
|
131
102
|
}
|
|
132
|
-
|
|
103
|
+
}
|
|
133
104
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
window.chatSearchState.lastScroll = $(this).scrollTop();
|
|
140
|
-
});
|
|
105
|
+
function buildAvatarHtml(user, sizePx, extraStyle = '', extraClasses = '') {
|
|
106
|
+
const sizeVal = sizePx + 'px';
|
|
107
|
+
const bgStyle = `background-color: ${user['icon:bgColor'] || '#5c5c5c'};`;
|
|
108
|
+
const commonStyle = `style="--avatar-size: ${sizeVal}; width: ${sizeVal}; height: ${sizeVal}; line-height: ${sizeVal}; ${bgStyle} ${extraStyle}"`;
|
|
109
|
+
const classes = `avatar avatar-rounded ${extraClasses}`;
|
|
141
110
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
111
|
+
if (user.picture) {
|
|
112
|
+
return `<span title="${user.username}" class="${classes}" component="avatar/picture" ${commonStyle}><img src="${user.picture}" alt="${user.username}" class="avatar avatar-rounded"></span>`;
|
|
113
|
+
}
|
|
145
114
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
115
|
+
const text = user['icon:text'] || (user.username ? user.username[0].toUpperCase() : '?');
|
|
116
|
+
return `<span title="${user.username}" class="${classes}" component="avatar/icon" ${commonStyle}>${text}</span>`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function renderMainAvatars(participants) {
|
|
120
|
+
if (!participants || participants.length === 0) {
|
|
121
|
+
return `<div class="main-avatar">
|
|
122
|
+
<span class="avatar avatar-rounded" style="--avatar-size: 32px; width:32px; height:32px; background-color: #ccc">?</span>
|
|
123
|
+
</div>`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return `<div class="main-avatar">
|
|
127
|
+
${buildAvatarHtml(participants[0], 32)}
|
|
128
|
+
</div>`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function cleanContent(content) {
|
|
132
|
+
if (!content) return '';
|
|
133
|
+
return content.replace(/<\/?p[^>]*>/g, ' ').trim();
|
|
149
134
|
}
|
|
150
135
|
|
|
151
136
|
function executeSearch() {
|
|
@@ -160,20 +145,14 @@ $(document).ready(function () {
|
|
|
160
145
|
}
|
|
161
146
|
|
|
162
147
|
let targetUid = ajaxify.data.uid || app.user.uid;
|
|
163
|
-
|
|
164
148
|
resultsContainer.show().html('<div class="text-center" style="padding:10px;"><i class="fa fa-spinner fa-spin"></i> מחפש...</div>');
|
|
165
149
|
window.chatSearchState.isOpen = true;
|
|
166
150
|
|
|
167
|
-
socket.emit('plugins.chatSearch.searchGlobal', {
|
|
168
|
-
query: query,
|
|
169
|
-
targetUid: targetUid
|
|
170
|
-
}, function (err, messages) {
|
|
151
|
+
socket.emit('plugins.chatSearch.searchGlobal', { query: query, targetUid: targetUid }, function (err, messages) {
|
|
171
152
|
if (err) {
|
|
172
|
-
console.error(err);
|
|
173
153
|
resultsContainer.html('<div class="alert alert-danger" style="margin:5px;">שגיאה</div>');
|
|
174
154
|
return;
|
|
175
155
|
}
|
|
176
|
-
|
|
177
156
|
if (!messages || messages.length === 0) {
|
|
178
157
|
const noRes = '<div class="text-center" style="padding:10px; color:#777;">לא נמצאו תוצאות.</div>';
|
|
179
158
|
resultsContainer.html(noRes);
|
|
@@ -181,59 +160,82 @@ $(document).ready(function () {
|
|
|
181
160
|
return;
|
|
182
161
|
}
|
|
183
162
|
|
|
184
|
-
let html = '<
|
|
185
|
-
|
|
163
|
+
let html = '<div class="d-flex flex-column">';
|
|
186
164
|
messages.forEach(msg => {
|
|
187
|
-
const
|
|
165
|
+
const isoTime = new Date(msg.timestamp).toISOString();
|
|
166
|
+
|
|
188
167
|
let baseUrl = window.location.pathname.replace(/\/chats\/.*$/, '/chats');
|
|
189
168
|
if (baseUrl.endsWith('/')) baseUrl = baseUrl.slice(0, -1);
|
|
190
|
-
|
|
169
|
+
|
|
191
170
|
const chatLink = baseUrl + '/' + msg.roomId + '?mid=' + msg.mid;
|
|
192
171
|
const senderName = (msg.user && msg.user.username) ? msg.user.username : 'Unknown';
|
|
172
|
+
|
|
173
|
+
const mainAvatarHtml = renderMainAvatars(msg.participants);
|
|
174
|
+
const senderSmallAvatar = buildAvatarHtml(msg.user, 14, 'vertical-align: text-bottom;', 'align-middle');
|
|
175
|
+
|
|
176
|
+
const cleanedContent = cleanContent(msg.content);
|
|
193
177
|
|
|
194
178
|
html += `
|
|
195
|
-
<
|
|
196
|
-
<div
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
179
|
+
<div component="chat/recent/room" class="rounded-1 search-result" data-roomid="${msg.roomId}">
|
|
180
|
+
<div class="d-flex gap-1 justify-content-between">
|
|
181
|
+
<a href="#" onclick="ajaxify.go('${chatLink}'); return false;" class="chat-room-btn position-relative d-flex flex-grow-1 gap-2 justify-content-start align-items-start btn btn-ghost btn-sm ff-sans text-start" style="padding: 0.5rem;">
|
|
182
|
+
|
|
183
|
+
${mainAvatarHtml}
|
|
184
|
+
|
|
185
|
+
<div class="d-flex flex-grow-1 flex-column w-100" style="min-width:0;">
|
|
186
|
+
<div component="chat/room/title" class="room-name fw-semibold text-xs text-break">
|
|
187
|
+
${msg.roomName}
|
|
188
|
+
</div>
|
|
189
|
+
<div component="chat/room/teaser">
|
|
190
|
+
|
|
191
|
+
<div class="teaser-content text-sm line-clamp-3 text-break mb-0">
|
|
192
|
+
${senderSmallAvatar}
|
|
193
|
+
<strong class="text-xs fw-semibold teaser-username">${senderName}:</strong>
|
|
194
|
+
${cleanedContent}
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<div class="teaser-timestamp text-muted text-xs" style="margin-top: 2px; line-height: 1;">
|
|
198
|
+
<span class="timeago" title="${isoTime}"></span>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
</a>
|
|
202
204
|
</div>
|
|
203
|
-
</
|
|
205
|
+
</div>
|
|
206
|
+
<hr class="my-1">
|
|
204
207
|
`;
|
|
205
208
|
});
|
|
206
|
-
html += '</
|
|
209
|
+
html += '</div>';
|
|
207
210
|
|
|
208
211
|
resultsContainer.html(html);
|
|
209
212
|
|
|
210
|
-
|
|
213
|
+
if ($.fn.timeago) {
|
|
214
|
+
resultsContainer.find('.timeago').timeago();
|
|
215
|
+
}
|
|
216
|
+
|
|
211
217
|
window.chatSearchState.resultsHtml = html;
|
|
212
218
|
window.chatSearchState.lastScroll = 0;
|
|
213
|
-
|
|
214
219
|
highlightActiveChat();
|
|
215
220
|
});
|
|
216
221
|
}
|
|
217
222
|
|
|
218
223
|
function highlightActiveChat() {
|
|
219
|
-
// מנסים לקחת RoomID מה-URL או מהמידע של NodeBB
|
|
220
224
|
let currentRoomId = ajaxify.data.roomId;
|
|
221
225
|
if (!currentRoomId) {
|
|
222
226
|
const match = window.location.pathname.match(/chats\/(\d+)/);
|
|
223
227
|
if (match) currentRoomId = match[1];
|
|
224
228
|
}
|
|
225
|
-
|
|
226
229
|
if (!currentRoomId) return;
|
|
227
|
-
|
|
228
|
-
$('.search-result
|
|
229
|
-
|
|
230
|
+
$('.search-result').removeClass('active');
|
|
231
|
+
const activeItem = $('.search-result[data-roomid="' + currentRoomId + '"]');
|
|
232
|
+
activeItem.addClass('active');
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
function handleScrollToMessage() {
|
|
233
236
|
const params = new URLSearchParams(window.location.search);
|
|
234
237
|
const mid = params.get('mid');
|
|
235
238
|
if (!mid) return;
|
|
236
|
-
|
|
237
239
|
scrollToId(mid);
|
|
238
240
|
let attempts = 0;
|
|
239
241
|
const scrollInt = setInterval(() => {
|