JohnSmith9982 commited on
Commit
93de920
1 Parent(s): 26e126a

Upload 4 files

Browse files
Files changed (3) hide show
  1. assets/custom.css +170 -23
  2. assets/custom.js +388 -5
  3. assets/external-scripts.js +2 -0
assets/custom.css CHANGED
@@ -1,6 +1,12 @@
1
  :root {
2
- --chatbot-color-light: #F3F3F3;
3
- --chatbot-color-dark: #121111;
 
 
 
 
 
 
4
  }
5
 
6
  #app_title {
@@ -13,13 +19,15 @@
13
  }
14
  #description {
15
  text-align: center;
16
- margin:16px 0
17
  }
18
 
19
- /* 覆盖gradio的页脚信息QAQ */
20
- /* footer {
21
- display: none !important;
22
- } */
 
 
23
  #footer {
24
  text-align: center;
25
  }
@@ -28,7 +36,7 @@
28
  }
29
  #footer .versions{
30
  font-size: 85%;
31
- opacity: 0.85;
32
  }
33
 
34
  #float_display {
@@ -70,7 +78,8 @@
70
  }
71
  #status_display p {
72
  font-size: .85em;
73
- font-family: monospace;
 
74
  color: var(--body-text-color-subdued);
75
  }
76
 
@@ -102,7 +111,7 @@
102
  }
103
  .progress-bar {
104
  background-color: var(--input-background-fill);;
105
- margin: 0 1em;
106
  height: 20px;
107
  border-radius: 10px;
108
  overflow: hidden;
@@ -135,7 +144,7 @@
135
  display: none !important;
136
  }
137
  .apSlider {
138
- background-color: var(--block-label-background-fill);
139
  bottom: 0;
140
  cursor: pointer;
141
  left: 0;
@@ -154,13 +163,47 @@
154
  content: "🌞";
155
  }
156
  input:checked + .apSlider {
157
- background-color: var(--block-label-background-fill);
158
  }
159
  input:checked + .apSlider::before {
160
  transform: translateX(23px);
161
  content:"🌚";
162
  }
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  #submit_btn, #cancel_btn {
165
  height: 42px !important;
166
  }
@@ -179,25 +222,25 @@ ol:not(.options), ul:not(.options) {
179
 
180
  /* 亮色(默认) */
181
  #chuanhu_chatbot {
182
- background-color: var(--chatbot-color-light) !important;
183
- color: #000000 !important;
184
  }
185
  [data-testid = "bot"] {
186
- background-color: #FFFFFF !important;
187
  }
188
  [data-testid = "user"] {
189
- background-color: #95EC69 !important;
190
  }
191
  /* 暗色 */
192
  .dark #chuanhu_chatbot {
193
- background-color: var(--chatbot-color-dark) !important;
194
- color: #FFFFFF !important;
195
  }
196
  .dark [data-testid = "bot"] {
197
- background-color: #2C2C2C !important;
198
  }
199
  .dark [data-testid = "user"] {
200
- background-color: #26B561 !important;
201
  }
202
 
203
  /* 屏幕宽度大于等于500px的设备 */
@@ -219,14 +262,17 @@ ol:not(.options), ul:not(.options) {
219
  max-height: calc(100vh - 140px - var(--line-sm)*1rem - 2*var(--block-label-margin) );
220
  }
221
  [data-testid = "bot"] {
222
- max-width: 98% !important;
223
  }
224
  #app_title h1{
225
  letter-spacing: -1px; font-size: 22px;
226
  }
227
  }
 
 
 
228
  /* 对话气泡 */
229
- [class *= "message"] {
230
  border-radius: var(--radius-xl) !important;
231
  border: none;
232
  padding: var(--spacing-xl) !important;
@@ -244,6 +290,104 @@ ol:not(.options), ul:not(.options) {
244
  width: auto !important;
245
  border-bottom-right-radius: 0 !important;
246
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  /* 表格 */
248
  table {
249
  margin: 1em 0;
@@ -277,10 +421,13 @@ pre code {
277
  background-color: hsla(0, 0%, 0%, 80%)!important;
278
  border-radius: 10px;
279
  padding: 1.4em 1.2em 0em 1.4em;
280
- margin: 1.2em 2em 1.2em 0.5em;
281
  color: #FFF;
282
  box-shadow: 6px 6px 16px hsla(0, 0%, 0%, 0.2);
283
  }
 
 
 
284
  /* 代码高亮样式 */
285
  .highlight .hll { background-color: #49483e }
286
  .highlight .c { color: #75715e } /* Comment */
 
1
  :root {
2
+ --chatbot-color-light: #000000;
3
+ --chatbot-color-dark: #FFFFFF;
4
+ --chatbot-background-color-light: #F3F3F3;
5
+ --chatbot-background-color-dark: #121111;
6
+ --message-user-background-color-light: #95EC69;
7
+ --message-user-background-color-dark: #26B561;
8
+ --message-bot-background-color-light: #FFFFFF;
9
+ --message-bot-background-color-dark: #2C2C2C;
10
  }
11
 
12
  #app_title {
 
19
  }
20
  #description {
21
  text-align: center;
22
+ margin: 32px 0 4px 0;
23
  }
24
 
25
+ /* gradio的页脚信息 */
26
+ footer {
27
+ /* display: none !important; */
28
+ margin-top: .2em !important;
29
+ font-size: 85%;
30
+ }
31
  #footer {
32
  text-align: center;
33
  }
 
36
  }
37
  #footer .versions{
38
  font-size: 85%;
39
+ opacity: 0.60;
40
  }
41
 
42
  #float_display {
 
78
  }
79
  #status_display p {
80
  font-size: .85em;
81
+ font-family: ui-monospace, "SF Mono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "Microsoft Yahei UI", "Microsoft Yahei", monospace;
82
+ /* Windows下中文的monospace会fallback为新宋体,实在太丑,这里折中使用微软雅黑 */
83
  color: var(--body-text-color-subdued);
84
  }
85
 
 
111
  }
112
  .progress-bar {
113
  background-color: var(--input-background-fill);;
114
+ margin: .5em 0 !important;
115
  height: 20px;
116
  border-radius: 10px;
117
  overflow: hidden;
 
144
  display: none !important;
145
  }
146
  .apSlider {
147
+ background-color: var(--neutral-200);
148
  bottom: 0;
149
  cursor: pointer;
150
  left: 0;
 
163
  content: "🌞";
164
  }
165
  input:checked + .apSlider {
166
+ background-color: var(--primary-600);
167
  }
168
  input:checked + .apSlider::before {
169
  transform: translateX(23px);
170
  content:"🌚";
171
  }
172
 
173
+ /* Override Slider Styles (for webkit browsers like Safari and Chrome)
174
+ * 好希望这份提案能早日实现 https://github.com/w3c/csswg-drafts/issues/4410
175
+ * 进度滑块在各个平台还是太不统一了
176
+ */
177
+ input[type="range"] {
178
+ -webkit-appearance: none;
179
+ height: 4px;
180
+ background: var(--input-background-fill);
181
+ border-radius: 5px;
182
+ background-image: linear-gradient(var(--primary-500),var(--primary-500));
183
+ background-size: 0% 100%;
184
+ background-repeat: no-repeat;
185
+ }
186
+ input[type="range"]::-webkit-slider-thumb {
187
+ -webkit-appearance: none;
188
+ height: 20px;
189
+ width: 20px;
190
+ border-radius: 50%;
191
+ border: solid 0.5px #ddd;
192
+ background-color: white;
193
+ cursor: ew-resize;
194
+ box-shadow: var(--input-shadow);
195
+ transition: background-color .1s ease;
196
+ }
197
+ input[type="range"]::-webkit-slider-thumb:hover {
198
+ background: var(--neutral-50);
199
+ }
200
+ input[type=range]::-webkit-slider-runnable-track {
201
+ -webkit-appearance: none;
202
+ box-shadow: none;
203
+ border: none;
204
+ background: transparent;
205
+ }
206
+
207
  #submit_btn, #cancel_btn {
208
  height: 42px !important;
209
  }
 
222
 
223
  /* 亮色(默认) */
224
  #chuanhu_chatbot {
225
+ background-color: var(--chatbot-background-color-light) !important;
226
+ color: var(--chatbot-color-light) !important;
227
  }
228
  [data-testid = "bot"] {
229
+ background-color: var(--message-bot-background-color-light) !important;
230
  }
231
  [data-testid = "user"] {
232
+ background-color: var(--message-user-background-color-light) !important;
233
  }
234
  /* 暗色 */
235
  .dark #chuanhu_chatbot {
236
+ background-color: var(--chatbot-background-color-dark) !important;
237
+ color: var(--chatbot-color-dark) !important;
238
  }
239
  .dark [data-testid = "bot"] {
240
+ background-color: var(--message-bot-background-color-dark) !important;
241
  }
242
  .dark [data-testid = "user"] {
243
+ background-color: var(--message-user-background-color-dark) !important;
244
  }
245
 
246
  /* 屏幕宽度大于等于500px的设备 */
 
262
  max-height: calc(100vh - 140px - var(--line-sm)*1rem - 2*var(--block-label-margin) );
263
  }
264
  [data-testid = "bot"] {
265
+ max-width: 95% !important;
266
  }
267
  #app_title h1{
268
  letter-spacing: -1px; font-size: 22px;
269
  }
270
  }
271
+ #chuanhu_chatbot .wrap {
272
+ overflow-x: hidden;
273
+ }
274
  /* 对话气泡 */
275
+ .message {
276
  border-radius: var(--radius-xl) !important;
277
  border: none;
278
  padding: var(--spacing-xl) !important;
 
290
  width: auto !important;
291
  border-bottom-right-radius: 0 !important;
292
  }
293
+
294
+ .message p {
295
+ margin-top: 0.6em !important;
296
+ margin-bottom: 0.6em !important;
297
+ }
298
+ .message p:first-child { margin-top: 0 !important; }
299
+ .message p:last-of-type { margin-bottom: 0 !important; }
300
+
301
+ .message .md-message {
302
+ display: block;
303
+ padding: 0 !important;
304
+ }
305
+ .message .raw-message {
306
+ display: block;
307
+ padding: 0 !important;
308
+ white-space: pre-wrap;
309
+ }
310
+ .raw-message.hideM, .md-message.hideM {
311
+ display: none;
312
+ }
313
+
314
+ /* custom buttons */
315
+ .chuanhu-btn {
316
+ border-radius: 5px;
317
+ /* background-color: #E6E6E6 !important; */
318
+ color: rgba(120, 120, 120, 0.64) !important;
319
+ padding: 4px !important;
320
+ position: absolute;
321
+ right: -22px;
322
+ cursor: pointer !important;
323
+ transition: color .2s ease, background-color .2s ease;
324
+ }
325
+ .chuanhu-btn:hover {
326
+ background-color: rgba(167, 167, 167, 0.25) !important;
327
+ color: unset !important;
328
+ }
329
+ .chuanhu-btn:active {
330
+ background-color: rgba(167, 167, 167, 0.5) !important;
331
+ }
332
+ .chuanhu-btn:focus {
333
+ outline: none;
334
+ }
335
+ .copy-bot-btn {
336
+ /* top: 18px; */
337
+ bottom: 0;
338
+ }
339
+ .toggle-md-btn {
340
+ /* top: 0; */
341
+ bottom: 20px;
342
+ }
343
+ .copy-code-btn {
344
+ position: relative;
345
+ float: right;
346
+ font-size: 1em;
347
+ cursor: pointer;
348
+ }
349
+
350
+ .message-wrap>div img{
351
+ border-radius: 10px !important;
352
+ }
353
+
354
+ /* history message */
355
+ .wrap>.history-message {
356
+ padding: 10px !important;
357
+ }
358
+ .history-message {
359
+ /* padding: 0 !important; */
360
+ opacity: 80%;
361
+ display: flex;
362
+ flex-direction: column;
363
+ }
364
+ .history-message>.history-message {
365
+ padding: 0 !important;
366
+ }
367
+ .history-message>.message-wrap {
368
+ padding: 0 !important;
369
+ margin-bottom: 16px;
370
+ }
371
+ .history-message>.message {
372
+ margin-bottom: 16px;
373
+ }
374
+ .wrap>.history-message::after {
375
+ content: "";
376
+ display: block;
377
+ height: 2px;
378
+ background-color: var(--body-text-color-subdued);
379
+ margin-bottom: 10px;
380
+ margin-top: -10px;
381
+ clear: both;
382
+ }
383
+ .wrap>.history-message>:last-child::after {
384
+ content: "仅供查看";
385
+ display: block;
386
+ text-align: center;
387
+ color: var(--body-text-color-subdued);
388
+ font-size: 0.8em;
389
+ }
390
+
391
  /* 表格 */
392
  table {
393
  margin: 1em 0;
 
421
  background-color: hsla(0, 0%, 0%, 80%)!important;
422
  border-radius: 10px;
423
  padding: 1.4em 1.2em 0em 1.4em;
424
+ margin: 0.6em 2em 1em 0.2em;
425
  color: #FFF;
426
  box-shadow: 6px 6px 16px hsla(0, 0%, 0%, 0.2);
427
  }
428
+ .message pre {
429
+ padding: 0 !important;
430
+ }
431
  /* 代码高亮样式 */
432
  .highlight .hll { background-color: #49483e }
433
  .highlight .c { color: #75715e } /* Comment */
assets/custom.js CHANGED
@@ -13,22 +13,51 @@ var user_input_tb = null;
13
  var userInfoDiv = null;
14
  var appTitleDiv = null;
15
  var chatbot = null;
 
16
  var apSwitch = null;
 
 
 
 
 
 
 
 
 
 
17
 
18
  var ga = document.getElementsByTagName("gradio-app");
19
  var targetNode = ga[0];
20
  var isInIframe = (window.self !== window.top);
 
 
 
 
 
 
 
 
 
21
 
22
  // gradio 页面加载好了么??? 我能动你的元素了么??
23
  function gradioLoaded(mutations) {
24
  for (var i = 0; i < mutations.length; i++) {
25
- if (mutations[i].addedNodes.length) {
 
26
  gradioContainer = document.querySelector(".gradio-container");
27
  user_input_tb = document.getElementById('user_input_tb');
28
  userInfoDiv = document.getElementById("user_info");
29
  appTitleDiv = document.getElementById("app_title");
30
  chatbot = document.querySelector('#chuanhu_chatbot');
 
31
  apSwitch = document.querySelector('.apSwitch input[type="checkbox"]');
 
 
 
 
 
 
 
32
 
33
  if (gradioContainer && apSwitch) { // gradioCainter 加载出来了没?
34
  adjustDarkMode();
@@ -37,15 +66,42 @@ function gradioLoaded(mutations) {
37
  selectHistory();
38
  }
39
  if (userInfoDiv && appTitleDiv) { // userInfoDiv 和 appTitleDiv 加载出来了没?
 
 
 
40
  setTimeout(showOrHideUserInfo(), 2000);
41
  }
42
  if (chatbot) { // chatbot 加载出来了没?
43
- setChatbotHeight()
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
  }
46
  }
47
  }
48
 
 
 
 
 
 
 
 
 
 
 
 
49
  function selectHistory() {
50
  user_input_ta = user_input_tb.querySelector("textarea");
51
  if (user_input_ta) {
@@ -94,6 +150,34 @@ function selectHistory() {
94
  }
95
  }
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  function toggleUserInfoVisibility(shouldHide) {
98
  if (userInfoDiv) {
99
  if (shouldHide) {
@@ -140,12 +224,12 @@ function showOrHideUserInfo() {
140
  appTitleDiv.ontouchend = function () {
141
  setTimeout(function () {
142
  toggleUserInfoVisibility(true);
143
- }, 3000);
144
  };
145
  userInfoDiv.ontouchend = function () {
146
  setTimeout(function () {
147
  toggleUserInfoVisibility(true);
148
- }, 3000);
149
  };
150
  sendBtn.ontouchend = function () {
151
  setTimeout(function () {
@@ -208,6 +292,297 @@ function setChatbotHeight() {
208
  }
209
  }
210
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
 
212
  // 监视页面内部 DOM 变动
213
  var observer = new MutationObserver(function (mutations) {
@@ -218,7 +593,15 @@ observer.observe(targetNode, { childList: true, subtree: true });
218
  // 监视页面变化
219
  window.addEventListener("DOMContentLoaded", function () {
220
  isInIframe = (window.self !== window.top);
 
 
221
  });
222
  window.addEventListener('resize', setChatbotHeight);
223
  window.addEventListener('scroll', setChatbotHeight);
224
- window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", adjustDarkMode);
 
 
 
 
 
 
 
13
  var userInfoDiv = null;
14
  var appTitleDiv = null;
15
  var chatbot = null;
16
+ var chatbotWrap = null;
17
  var apSwitch = null;
18
+ var empty_botton = null;
19
+ var messageBotDivs = null;
20
+ // var renderLatex = null;
21
+ var loginUserForm = null;
22
+ var logginUser = null;
23
+
24
+ var userLogged = false;
25
+ var usernameGotten = false;
26
+ var shouldRenderLatex = false;
27
+ var historyLoaded = false;
28
 
29
  var ga = document.getElementsByTagName("gradio-app");
30
  var targetNode = ga[0];
31
  var isInIframe = (window.self !== window.top);
32
+ var language = navigator.language.slice(0,2);
33
+
34
+ var forView_i18n = {
35
+ 'zh': "仅供查看",
36
+ 'en': "For viewing only",
37
+ 'ja': "閲覧専用",
38
+ 'fr': "Pour consultation seulement",
39
+ 'es': "Solo para visualización",
40
+ };
41
 
42
  // gradio 页面加载好了么??? 我能动你的元素了么??
43
  function gradioLoaded(mutations) {
44
  for (var i = 0; i < mutations.length; i++) {
45
+ if (mutations[i].addedNodes.length) {
46
+ loginUserForm = document.querySelector(".gradio-container > .main > .wrap > .panel > .form")
47
  gradioContainer = document.querySelector(".gradio-container");
48
  user_input_tb = document.getElementById('user_input_tb');
49
  userInfoDiv = document.getElementById("user_info");
50
  appTitleDiv = document.getElementById("app_title");
51
  chatbot = document.querySelector('#chuanhu_chatbot');
52
+ chatbotWrap = document.querySelector('#chuanhu_chatbot > .wrap');
53
  apSwitch = document.querySelector('.apSwitch input[type="checkbox"]');
54
+ // renderLatex = document.querySelector("#render_latex_checkbox > label > input");
55
+ empty_botton = document.getElementById("empty_btn")
56
+
57
+ if (loginUserForm) {
58
+ localStorage.setItem("userLogged", true);
59
+ userLogged = true;
60
+ }
61
 
62
  if (gradioContainer && apSwitch) { // gradioCainter 加载出来了没?
63
  adjustDarkMode();
 
66
  selectHistory();
67
  }
68
  if (userInfoDiv && appTitleDiv) { // userInfoDiv 和 appTitleDiv 加载出来了没?
69
+ if (!usernameGotten) {
70
+ getUserInfo();
71
+ }
72
  setTimeout(showOrHideUserInfo(), 2000);
73
  }
74
  if (chatbot) { // chatbot 加载出来了没?
75
+ setChatbotHeight();
76
+ }
77
+ if (chatbotWrap) {
78
+ if (!historyLoaded) {
79
+ loadHistoryHtml();
80
+ }
81
+ setChatbotScroll();
82
+ }
83
+ // if (renderLatex) { // renderLatex 加载出来了没?
84
+ // shouldRenderLatex = renderLatex.checked;
85
+ // updateMathJax();
86
+ // }
87
+ if (empty_botton) {
88
+ emptyHistory();
89
  }
90
  }
91
  }
92
  }
93
 
94
+ function webLocale() {
95
+ console.log("webLocale", language);
96
+ if (forView_i18n.hasOwnProperty(language)) {
97
+ var forView = forView_i18n[language];
98
+ var forViewStyle = document.createElement('style');
99
+ forViewStyle.innerHTML = '.wrap>.history-message>:last-child::after { content: "' + forView + '"!important; }';
100
+ document.head.appendChild(forViewStyle);
101
+ // console.log("added forViewStyle", forView);
102
+ }
103
+ }
104
+
105
  function selectHistory() {
106
  user_input_ta = user_input_tb.querySelector("textarea");
107
  if (user_input_ta) {
 
150
  }
151
  }
152
 
153
+ var username = null;
154
+ function getUserInfo() {
155
+ if (usernameGotten) {
156
+ return;
157
+ }
158
+ userLogged = localStorage.getItem('userLogged');
159
+ if (userLogged) {
160
+ username = userInfoDiv.innerText;
161
+ if (username) {
162
+ if (username.includes("getting user info…")) {
163
+ setTimeout(getUserInfo, 500);
164
+ return;
165
+ } else if (username === " ") {
166
+ localStorage.removeItem("username");
167
+ localStorage.removeItem("userLogged")
168
+ userLogged = false;
169
+ usernameGotten = true;
170
+ return;
171
+ } else {
172
+ username = username.match(/User:\s*(.*)/)[1] || username;
173
+ localStorage.setItem("username", username);
174
+ usernameGotten = true;
175
+ clearHistoryHtml();
176
+ }
177
+ }
178
+ }
179
+ }
180
+
181
  function toggleUserInfoVisibility(shouldHide) {
182
  if (userInfoDiv) {
183
  if (shouldHide) {
 
224
  appTitleDiv.ontouchend = function () {
225
  setTimeout(function () {
226
  toggleUserInfoVisibility(true);
227
+ }, 3000);
228
  };
229
  userInfoDiv.ontouchend = function () {
230
  setTimeout(function () {
231
  toggleUserInfoVisibility(true);
232
+ }, 3000);
233
  };
234
  sendBtn.ontouchend = function () {
235
  setTimeout(function () {
 
292
  }
293
  }
294
  }
295
+ function setChatbotScroll() {
296
+ var scrollHeight = chatbotWrap.scrollHeight;
297
+ chatbotWrap.scrollTo(0,scrollHeight)
298
+ }
299
+ var rangeInputs = null;
300
+ var numberInputs = null;
301
+ function setSlider() {
302
+ rangeInputs = document.querySelectorAll('input[type="range"]');
303
+ numberInputs = document.querySelectorAll('input[type="number"]')
304
+ setSliderRange();
305
+ rangeInputs.forEach(rangeInput => {
306
+ rangeInput.addEventListener('input', setSliderRange);
307
+ });
308
+ numberInputs.forEach(numberInput => {
309
+ numberInput.addEventListener('input', setSliderRange);
310
+ })
311
+ }
312
+ function setSliderRange() {
313
+ var range = document.querySelectorAll('input[type="range"]');
314
+ range.forEach(range => {
315
+ range.style.backgroundSize = (range.value - range.min) / (range.max - range.min) * 100 + '% 100%';
316
+ });
317
+ }
318
+
319
+ function addChuanhuButton(botElement) {
320
+ var rawMessage = null;
321
+ var mdMessage = null;
322
+ rawMessage = botElement.querySelector('.raw-message');
323
+ mdMessage = botElement.querySelector('.md-message');
324
+ if (!rawMessage) {
325
+ var buttons = botElement.querySelectorAll('button.chuanhu-btn');
326
+ for (var i = 0; i < buttons.length; i++) {
327
+ buttons[i].parentNode.removeChild(buttons[i]);
328
+ }
329
+ return;
330
+ }
331
+ var copyButton = null;
332
+ var toggleButton = null;
333
+ copyButton = botElement.querySelector('button.copy-bot-btn');
334
+ toggleButton = botElement.querySelector('button.toggle-md-btn');
335
+ if (copyButton) copyButton.remove();
336
+ if (toggleButton) toggleButton.remove();
337
+
338
+ // Copy bot button
339
+ var copyButton = document.createElement('button');
340
+ copyButton.classList.add('chuanhu-btn');
341
+ copyButton.classList.add('copy-bot-btn');
342
+ copyButton.setAttribute('aria-label', 'Copy');
343
+ copyButton.innerHTML = copyIcon;
344
+ copyButton.addEventListener('click', () => {
345
+ const textToCopy = rawMessage.innerText;
346
+ navigator.clipboard
347
+ .writeText(textToCopy)
348
+ .then(() => {
349
+ copyButton.innerHTML = copiedIcon;
350
+ setTimeout(() => {
351
+ copyButton.innerHTML = copyIcon;
352
+ }, 1500);
353
+ })
354
+ .catch(() => {
355
+ console.error("copy failed");
356
+ });
357
+ });
358
+ botElement.appendChild(copyButton);
359
+
360
+ // Toggle button
361
+ var toggleButton = document.createElement('button');
362
+ toggleButton.classList.add('chuanhu-btn');
363
+ toggleButton.classList.add('toggle-md-btn');
364
+ toggleButton.setAttribute('aria-label', 'Toggle');
365
+ var renderMarkdown = mdMessage.classList.contains('hideM');
366
+ toggleButton.innerHTML = renderMarkdown ? mdIcon : rawIcon;
367
+ toggleButton.addEventListener('click', () => {
368
+ renderMarkdown = mdMessage.classList.contains('hideM');
369
+ if (renderMarkdown){
370
+ renderMarkdownText(botElement);
371
+ toggleButton.innerHTML=rawIcon;
372
+ } else {
373
+ removeMarkdownText(botElement);
374
+ toggleButton.innerHTML=mdIcon;
375
+ }
376
+ });
377
+ botElement.insertBefore(toggleButton, copyButton);
378
+ }
379
+
380
+ function addCopyCodeButton(pre) {
381
+ var code = null;
382
+ var firstChild = null;
383
+ code = pre.querySelector('code');
384
+ if (!code) return;
385
+ firstChild = code.querySelector('div');
386
+ if (!firstChild) return;
387
+ var oldCopyButton = null;
388
+ oldCopyButton = code.querySelector('button.copy-code-btn');
389
+ // if (oldCopyButton) oldCopyButton.remove();
390
+ if (oldCopyButton) return; // 没太有用,新生成的对话中始终会被pre覆盖,导致按钮消失,这段代码不启用……
391
+ var codeButton = document.createElement('button');
392
+ codeButton.classList.add('copy-code-btn');
393
+ codeButton.textContent = '\uD83D\uDCCE';
394
+
395
+ code.insertBefore(codeButton, firstChild);
396
+ codeButton.addEventListener('click', function () {
397
+ var range = document.createRange();
398
+ range.selectNodeContents(code);
399
+ range.setStartBefore(firstChild);
400
+ navigator.clipboard
401
+ .writeText(range.toString())
402
+ .then(() => {
403
+ codeButton.textContent = '\u2714';
404
+ setTimeout(function () {
405
+ codeButton.textContent = '\uD83D\uDCCE';
406
+ }, 2000);
407
+ })
408
+ .catch(e => {
409
+ console.error(e);
410
+ codeButton.textContent = '\u2716';
411
+ });
412
+ });
413
+ }
414
+
415
+ function renderMarkdownText(message) {
416
+ var mdDiv = message.querySelector('.md-message');
417
+ if (mdDiv) mdDiv.classList.remove('hideM');
418
+ var rawDiv = message.querySelector('.raw-message');
419
+ if (rawDiv) rawDiv.classList.add('hideM');
420
+ }
421
+ function removeMarkdownText(message) {
422
+ var rawDiv = message.querySelector('.raw-message');
423
+ if (rawDiv) rawDiv.classList.remove('hideM');
424
+ var mdDiv = message.querySelector('.md-message');
425
+ if (mdDiv) mdDiv.classList.add('hideM');
426
+ }
427
+
428
+ var rendertime = 0; // for debugging
429
+ var mathjaxUpdated = false;
430
+
431
+ function renderMathJax() {
432
+ messageBotDivs = document.querySelectorAll('.message.bot .md-message');
433
+ for (var i = 0; i < messageBotDivs.length; i++) {
434
+ var mathJaxSpan = messageBotDivs[i].querySelector('.MathJax_Preview');
435
+ if (!mathJaxSpan && shouldRenderLatex && !mathjaxUpdated) {
436
+ MathJax.Hub.Queue(["Typeset", MathJax.Hub, messageBotDivs[i]]);
437
+ rendertime +=1; // for debugging
438
+ // console.log("renderingMathJax", i)
439
+ }
440
+ }
441
+ mathjaxUpdated = true;
442
+ // console.log("MathJax Rendered")
443
+ }
444
+
445
+ function removeMathjax() {
446
+ // var jax = MathJax.Hub.getAllJax();
447
+ // for (var i = 0; i < jax.length; i++) {
448
+ // // MathJax.typesetClear(jax[i]);
449
+ // jax[i].Text(newmath)
450
+ // jax[i].Reprocess()
451
+ // }
452
+ // 我真的不会了啊啊啊,mathjax并没有提供转换为原先文本的办法。
453
+ mathjaxUpdated = true;
454
+ // console.log("MathJax removed!");
455
+ }
456
+
457
+ function updateMathJax() {
458
+ // renderLatex.addEventListener("change", function() {
459
+ // shouldRenderLatex = renderLatex.checked;
460
+ // if (!mathjaxUpdated) {
461
+ // if (shouldRenderLatex) {
462
+ // renderMathJax();
463
+ // } else {
464
+ // console.log("MathJax Disabled")
465
+ // removeMathjax();
466
+ // }
467
+ // } else {
468
+ // if (!shouldRenderLatex) {
469
+ // mathjaxUpdated = false; // reset
470
+ // }
471
+ // }
472
+ // });
473
+ if (shouldRenderLatex && !mathjaxUpdated) {
474
+ renderMathJax();
475
+ }
476
+ mathjaxUpdated = false;
477
+ }
478
+
479
+ let timeoutId;
480
+ let isThrottled = false;
481
+ var mmutation
482
+ // 监听所有元素中 bot message 的变化,用来查找需要渲染的mathjax, 并为 bot 消息添加复制按钮。
483
+ var mObserver = new MutationObserver(function (mutationsList) {
484
+ for (mmutation of mutationsList) {
485
+ if (mmutation.type === 'childList') {
486
+ for (var node of mmutation.addedNodes) {
487
+ if (node.nodeType === 1 && node.classList.contains('message') && node.getAttribute('data-testid') === 'bot') {
488
+ if (shouldRenderLatex) {
489
+ renderMathJax();
490
+ mathjaxUpdated = false;
491
+ }
492
+ saveHistoryHtml();
493
+ document.querySelectorAll('#chuanhu_chatbot>.wrap>.message-wrap .message.bot').forEach(addChuanhuButton);
494
+ document.querySelectorAll('#chuanhu_chatbot>.wrap>.message-wrap .message.bot pre').forEach(addCopyCodeButton);
495
+ }
496
+ if (node.tagName === 'INPUT' && node.getAttribute('type') === 'range') {
497
+ setSlider();
498
+ }
499
+ }
500
+ for (var node of mmutation.removedNodes) {
501
+ if (node.nodeType === 1 && node.classList.contains('message') && node.getAttribute('data-testid') === 'bot') {
502
+ if (shouldRenderLatex) {
503
+ renderMathJax();
504
+ mathjaxUpdated = false;
505
+ }
506
+ saveHistoryHtml();
507
+ document.querySelectorAll('#chuanhu_chatbot>.wrap>.message-wrap .message.bot').forEach(addChuanhuButton);
508
+ document.querySelectorAll('#chuanhu_chatbot>.wrap>.message-wrap .message.bot pre').forEach(addCopyCodeButton);
509
+ }
510
+ }
511
+ } else if (mmutation.type === 'attributes') {
512
+ if (mmutation.target.nodeType === 1 && mmutation.target.classList.contains('message') && mmutation.target.getAttribute('data-testid') === 'bot') {
513
+ document.querySelectorAll('#chuanhu_chatbot>.wrap>.message-wrap .message.bot pre').forEach(addCopyCodeButton); // 目前写的是有点问题的,会导致加button次数过多,但是bot对话内容生成时又是不断覆盖pre的……
514
+ if (isThrottled) break; // 为了防止重复不断疯狂渲染,加上等待_(:з」∠)_
515
+ isThrottled = true;
516
+ clearTimeout(timeoutId);
517
+ timeoutId = setTimeout(() => {
518
+ isThrottled = false;
519
+ if (shouldRenderLatex) {
520
+ renderMathJax();
521
+ mathjaxUpdated = false;
522
+ }
523
+ document.querySelectorAll('#chuanhu_chatbot>.wrap>.message-wrap .message.bot').forEach(addChuanhuButton);
524
+ saveHistoryHtml();
525
+ }, 500);
526
+ }
527
+ }
528
+ }
529
+ });
530
+ mObserver.observe(document.documentElement, { attributes: true, childList: true, subtree: true });
531
+
532
+ var loadhistorytime = 0; // for debugging
533
+ function saveHistoryHtml() {
534
+ var historyHtml = document.querySelector('#chuanhu_chatbot > .wrap');
535
+ localStorage.setItem('chatHistory', historyHtml.innerHTML);
536
+ // console.log("History Saved")
537
+ historyLoaded = false;
538
+ }
539
+ function loadHistoryHtml() {
540
+ var historyHtml = localStorage.getItem('chatHistory');
541
+ if (!historyHtml) {
542
+ historyLoaded = true;
543
+ return; // no history, do nothing
544
+ }
545
+ userLogged = localStorage.getItem('userLogged');
546
+ if (userLogged){
547
+ historyLoaded = true;
548
+ return; // logged in, do nothing
549
+ }
550
+ if (!historyLoaded) {
551
+ var tempDiv = document.createElement('div');
552
+ tempDiv.innerHTML = historyHtml;
553
+ var buttons = tempDiv.querySelectorAll('button.chuanhu-btn');
554
+ for (var i = 0; i < buttons.length; i++) {
555
+ buttons[i].parentNode.removeChild(buttons[i]);
556
+ }
557
+ var fakeHistory = document.createElement('div');
558
+ fakeHistory.classList.add('history-message');
559
+ fakeHistory.innerHTML = tempDiv.innerHTML;
560
+ webLocale();
561
+ chatbotWrap.insertBefore(fakeHistory, chatbotWrap.firstChild);
562
+ // var fakeHistory = document.createElement('div');
563
+ // fakeHistory.classList.add('history-message');
564
+ // fakeHistory.innerHTML = historyHtml;
565
+ // chatbotWrap.insertBefore(fakeHistory, chatbotWrap.firstChild);
566
+ historyLoaded = true;
567
+ console.log("History Loaded");
568
+ loadhistorytime += 1; // for debugging
569
+ } else {
570
+ historyLoaded = false;
571
+ }
572
+ }
573
+ function clearHistoryHtml() {
574
+ localStorage.removeItem("chatHistory");
575
+ historyMessages = chatbotWrap.querySelector('.history-message');
576
+ if (historyMessages) {
577
+ chatbotWrap.removeChild(historyMessages);
578
+ console.log("History Cleared");
579
+ }
580
+ }
581
+ function emptyHistory() {
582
+ empty_botton.addEventListener("click", function () {
583
+ clearHistoryHtml();
584
+ });
585
+ }
586
 
587
  // 监视页面内部 DOM 变动
588
  var observer = new MutationObserver(function (mutations) {
 
593
  // 监视页面变化
594
  window.addEventListener("DOMContentLoaded", function () {
595
  isInIframe = (window.self !== window.top);
596
+ historyLoaded = false;
597
+ shouldRenderLatex = !!document.querySelector('script[src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"]');
598
  });
599
  window.addEventListener('resize', setChatbotHeight);
600
  window.addEventListener('scroll', setChatbotHeight);
601
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", adjustDarkMode);
602
+
603
+ // button svg code
604
+ const copyIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></span>';
605
+ const copiedIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><polyline points="20 6 9 17 4 12"></polyline></svg></span>';
606
+ const mdIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="1" viewBox="0 0 14 18" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><g transform-origin="center" transform="scale(0.85)"><path d="M1.5,0 L12.5,0 C13.3284271,-1.52179594e-16 14,0.671572875 14,1.5 L14,16.5 C14,17.3284271 13.3284271,18 12.5,18 L1.5,18 C0.671572875,18 1.01453063e-16,17.3284271 0,16.5 L0,1.5 C-1.01453063e-16,0.671572875 0.671572875,1.52179594e-16 1.5,0 Z" stroke-width="1.8"></path><line x1="3.5" y1="3.5" x2="10.5" y2="3.5"></line><line x1="3.5" y1="6.5" x2="8" y2="6.5"></line></g><path d="M4,9 L10,9 C10.5522847,9 11,9.44771525 11,10 L11,13.5 C11,14.0522847 10.5522847,14.5 10,14.5 L4,14.5 C3.44771525,14.5 3,14.0522847 3,13.5 L3,10 C3,9.44771525 3.44771525,9 4,9 Z" stroke="none" fill="currentColor"></path></svg></span>';
607
+ const rawIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="1.8" viewBox="0 0 18 14" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><g transform-origin="center" transform="scale(0.85)"><polyline points="4 3 0 7 4 11"></polyline><polyline points="14 3 18 7 14 11"></polyline><line x1="12" y1="0" x2="6" y2="14"></line></g></svg></span>';
assets/external-scripts.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+
2
+ // external javascript here