Keldos commited on
Commit
fb66964
·
1 Parent(s): 37526ea

fix: 修复一直重复生成对话按钮的问题,优化性能,避免鼠标悬浮时闪烁

Browse files
web_assets/javascript/ChuanhuChat.js CHANGED
@@ -12,6 +12,7 @@ var user_input_tb = null;
12
  var userInfoDiv = null;
13
  var appTitleDiv = null;
14
  var chatbot = null;
 
15
  var chatbotWrap = null;
16
  var apSwitch = null;
17
  var messageBotDivs = null;
@@ -43,7 +44,7 @@ function gradioLoaded(mutations) {
43
  }
44
 
45
  function initialize() {
46
- var needInit = {gradioContainer, apSwitch, user_input_tb, userInfoDiv, appTitleDiv, chatbot, chatbotWrap, statusDisplay, sliders, updateChuanhuBtn};
47
  initialized = true;
48
 
49
  loginUserForm = gradioApp().querySelector(".gradio-container > .main > .wrap > .panel > .form")
@@ -52,6 +53,7 @@ function initialize() {
52
  userInfoDiv = gradioApp().getElementById("user-info");
53
  appTitleDiv = gradioApp().getElementById("app-title");
54
  chatbot = gradioApp().querySelector('#chuanhu-chatbot');
 
55
  chatbotWrap = gradioApp().querySelector('#chuanhu-chatbot > .wrapper > .wrap');
56
  apSwitch = gradioApp().querySelector('.apSwitch input[type="checkbox"]');
57
  updateToast = gradioApp().querySelector("#toast-update");
@@ -82,8 +84,7 @@ function initialize() {
82
  setSlider();
83
  if (!historyLoaded) loadHistoryHtml();
84
  if (!usernameGotten) getUserInfo();
85
- mObserver.observe(chatbotWrap, { attributes: true, childList: true, subtree: true, characterData: true });
86
- submitObserver.observe(cancelBtn, { attributes: true, characterData: true });
87
 
88
  const lastCheckTime = localStorage.getItem('lastCheckTime') || 0;
89
  const longTimeNoCheck = currentTime - lastCheckTime > 3 * 24 * 60 * 60 * 1000;
@@ -221,43 +222,21 @@ function setChatbotScroll() {
221
  }
222
 
223
 
224
- let timeoutId;
225
- let isThrottled = false;
226
- // 监听chatWrap元素的变化,为 bot 消息添加复制按钮。
227
- var mObserver = new MutationObserver(function (mutationsList) {
228
- for (const mmutation of mutationsList) {
229
- if (mmutation.type === 'childList') {
230
- for (var node of mmutation.addedNodes) {
231
- if (node.nodeType === 1 && node.classList.contains('message')) {
232
- saveHistoryHtml();
233
- disableSendBtn();
234
- document.querySelectorAll('#chuanhu-chatbot .message-wrap .message.bot').forEach(addChuanhuButton);
235
- }
236
- }
237
- for (var node of mmutation.removedNodes) {
238
- if (node.nodeType === 1 && node.classList.contains('message')) {
239
- saveHistoryHtml();
240
- disableSendBtn();
241
- document.querySelectorAll('#chuanhu-chatbot .message-wrap .message.bot').forEach(addChuanhuButton);
242
- }
243
- }
244
- } else if (mmutation.type === 'attributes') {
245
- if (isThrottled) break; // 为了防止重复不断疯狂渲染,加上等待_(:з」∠)_
246
- isThrottled = true;
247
- clearTimeout(timeoutId);
248
- timeoutId = setTimeout(() => {
249
- isThrottled = false;
250
- document.querySelectorAll('#chuanhu-chatbot .message-wrap .message.bot').forEach(addChuanhuButton);
251
- saveHistoryHtml();
252
- disableSendBtn();
253
- }, 1500);
254
- }
255
  }
256
- });
 
257
 
258
- var submitObserver = new MutationObserver(function (mutationsList) {
259
- document.querySelectorAll('#chuanhu-chatbot .message-wrap .message.bot').forEach(addChuanhuButton);
260
- saveHistoryHtml();
 
261
  });
262
 
263
  // 监视页面内部 DOM 变动
 
12
  var userInfoDiv = null;
13
  var appTitleDiv = null;
14
  var chatbot = null;
15
+ var chatbotIndicator = null;
16
  var chatbotWrap = null;
17
  var apSwitch = null;
18
  var messageBotDivs = null;
 
44
  }
45
 
46
  function initialize() {
47
+ var needInit = {gradioContainer, apSwitch, user_input_tb, userInfoDiv, appTitleDiv, chatbot, chatbotIndicator, chatbotWrap, statusDisplay, sliders, updateChuanhuBtn};
48
  initialized = true;
49
 
50
  loginUserForm = gradioApp().querySelector(".gradio-container > .main > .wrap > .panel > .form")
 
53
  userInfoDiv = gradioApp().getElementById("user-info");
54
  appTitleDiv = gradioApp().getElementById("app-title");
55
  chatbot = gradioApp().querySelector('#chuanhu-chatbot');
56
+ chatbotIndicator = gradioApp().querySelector('#chuanhu-chatbot>div.wrap');
57
  chatbotWrap = gradioApp().querySelector('#chuanhu-chatbot > .wrapper > .wrap');
58
  apSwitch = gradioApp().querySelector('.apSwitch input[type="checkbox"]');
59
  updateToast = gradioApp().querySelector("#toast-update");
 
84
  setSlider();
85
  if (!historyLoaded) loadHistoryHtml();
86
  if (!usernameGotten) getUserInfo();
87
+ chatbotObserver.observe(chatbotIndicator, { attributes: true });
 
88
 
89
  const lastCheckTime = localStorage.getItem('lastCheckTime') || 0;
90
  const longTimeNoCheck = currentTime - lastCheckTime > 3 * 24 * 60 * 60 * 1000;
 
222
  }
223
 
224
 
225
+ function chatbotContentChanged(attempt = 1) {
226
+ for (var i = 0; i < attempt; i++) {
227
+ setTimeout(() => {
228
+ saveHistoryHtml();
229
+ disableSendBtn();
230
+ gradioApp().querySelectorAll('#chuanhu-chatbot .message-wrap .message.bot').forEach(addChuanhuButton);
231
+ }, i === 0 ? 0 : 500);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  }
233
+ // 理论上是不需要多次尝试执行的,可惜gradio的bug导致message可能没有渲染完毕,所以尝试500ms后再次执行
234
+ }
235
 
236
+ var chatbotObserver = new MutationObserver(() => {
237
+ if (chatbotIndicator.classList.contains('hide')) {
238
+ chatbotContentChanged(2);
239
+ }
240
  });
241
 
242
  // 监视页面内部 DOM 变动
web_assets/javascript/chat-history.js CHANGED
@@ -25,14 +25,6 @@ function loadHistoryHtml() {
25
  return; // logged in, do nothing
26
  }
27
  if (!historyLoaded) {
28
- var buttons = tempDiv.querySelectorAll('button.chuanhu-btn');
29
- var gradioCopyButtons = tempDiv.querySelectorAll('button.copy_code_button');
30
- for (var i = 0; i < buttons.length; i++) {
31
- buttons[i].parentNode.removeChild(buttons[i]);
32
- }
33
- for (var i = 0; i < gradioCopyButtons.length; i++) {
34
- gradioCopyButtons[i].parentNode.removeChild(gradioCopyButtons[i]);
35
- }
36
  var fakeHistory = document.createElement('div');
37
  fakeHistory.classList.add('history-message');
38
  fakeHistory.innerHTML = tempDiv.innerHTML;
 
25
  return; // logged in, do nothing
26
  }
27
  if (!historyLoaded) {
 
 
 
 
 
 
 
 
28
  var fakeHistory = document.createElement('div');
29
  fakeHistory.classList.add('history-message');
30
  fakeHistory.innerHTML = tempDiv.innerHTML;
web_assets/javascript/message-button.js CHANGED
@@ -4,20 +4,15 @@
4
  function addChuanhuButton(botElement) {
5
  var rawMessage = botElement.querySelector('.raw-message');
6
  var mdMessage = botElement.querySelector('.md-message');
7
- // var gradioCopyMsgBtn = botElement.querySelector('div.icon-button>button[title="copy"]'); // 获取 gradio 的 copy button,它可以读取真正的原始 message
8
- if (!rawMessage) {
9
  var buttons = botElement.querySelectorAll('button.chuanhu-btn');
10
  for (var i = 0; i < buttons.length; i++) {
11
  buttons[i].parentNode.removeChild(buttons[i]);
12
  }
13
  return;
14
  }
15
- var oldCopyButton = null;
16
- var oldToggleButton = null;
17
- oldCopyButton = botElement.querySelector('button.copy-bot-btn');
18
- oldToggleButton = botElement.querySelector('button.toggle-md-btn');
19
- if (oldCopyButton) oldCopyButton.remove();
20
- if (oldToggleButton) oldToggleButton.remove();
21
 
22
  // Copy bot button
23
  var copyButton = document.createElement('button');
@@ -66,13 +61,14 @@ function addChuanhuButton(botElement) {
66
  toggleButton.innerHTML = renderMarkdown ? mdIcon : rawIcon;
67
  toggleButton.addEventListener('click', () => {
68
  renderMarkdown = mdMessage.classList.contains('hideM');
69
- if (renderMarkdown){
70
  renderMarkdownText(botElement);
71
  toggleButton.innerHTML=rawIcon;
72
  } else {
73
  removeMarkdownText(botElement);
74
  toggleButton.innerHTML=mdIcon;
75
  }
 
76
  });
77
  botElement.insertBefore(toggleButton, copyButton);
78
 
@@ -85,8 +81,7 @@ function addChuanhuButton(botElement) {
85
  function removeMarkdownText(message) {
86
  var rawDiv = message.querySelector('.raw-message');
87
  if (rawDiv) {
88
- rawPre = rawDiv.querySelector('pre');
89
- if (rawPre) rawDiv.innerHTML = rawPre.innerHTML;
90
  rawDiv.classList.remove('hideM');
91
  }
92
  var mdDiv = message.querySelector('.md-message');
 
4
  function addChuanhuButton(botElement) {
5
  var rawMessage = botElement.querySelector('.raw-message');
6
  var mdMessage = botElement.querySelector('.md-message');
7
+
8
+ if (!rawMessage) { // 如果没有 raw message,说明是早期历史记录,去除按钮
9
  var buttons = botElement.querySelectorAll('button.chuanhu-btn');
10
  for (var i = 0; i < buttons.length; i++) {
11
  buttons[i].parentNode.removeChild(buttons[i]);
12
  }
13
  return;
14
  }
15
+ botElement.querySelectorAll('button.copy-bot-btn, button.toggle-md-btn').forEach(btn => btn.remove()); // 就算原先有了,也必须重新添加,而不是跳过
 
 
 
 
 
16
 
17
  // Copy bot button
18
  var copyButton = document.createElement('button');
 
61
  toggleButton.innerHTML = renderMarkdown ? mdIcon : rawIcon;
62
  toggleButton.addEventListener('click', () => {
63
  renderMarkdown = mdMessage.classList.contains('hideM');
64
+ if (renderMarkdown) {
65
  renderMarkdownText(botElement);
66
  toggleButton.innerHTML=rawIcon;
67
  } else {
68
  removeMarkdownText(botElement);
69
  toggleButton.innerHTML=mdIcon;
70
  }
71
+ chatbotContentChanged(1); // to set md or raw in read-only history html
72
  });
73
  botElement.insertBefore(toggleButton, copyButton);
74
 
 
81
  function removeMarkdownText(message) {
82
  var rawDiv = message.querySelector('.raw-message');
83
  if (rawDiv) {
84
+ rawDiv.innerHTML = rawDiv.querySelector('pre')?.innerHTML || rawDiv.innerHTML;
 
85
  rawDiv.classList.remove('hideM');
86
  }
87
  var mdDiv = message.querySelector('.md-message');