Keldos commited on
Commit
0618646
1 Parent(s): a13de87

feat: 页面加载后自动隐藏user_display, 但在点击相关元素时显示

Browse files

- 改变了上次的组件布局
- 做了一个很丑陋的 user label, 但是能用吧。能用就行。
- 使用了js......大量js, 同时整理了之前的js缩进和DOM监听事件
现在 user label 具体的显示逻辑是:
1. 页面加载后延迟显示4s;
2. 鼠标移动到或手指点击“川虎ChatGPT标题”、“user_info”区域、发送框时显示, 离开或touch结束时隐藏;
3. 手指点击会延迟显示3秒。鼠标移动无延迟;
4. CSS中设定显示动画: 出现0.3s, 消失1s.
- float_display里还可以自由地补充布局任何元素, 都可以采用这种办法
- 同时加大了小屏幕chatbot气泡宽度, resolve #515

Files changed (4) hide show
  1. ChuanhuChatbot.py +5 -5
  2. assets/custom.css +37 -9
  3. assets/custom.js +132 -52
  4. modules/presets.py +2 -4
ChuanhuChatbot.py CHANGED
@@ -30,10 +30,10 @@ with gr.Blocks(css=customCSS, theme=small_and_beautiful_theme) as demo:
30
  topic = gr.State("未命名对话历史记录")
31
 
32
  with gr.Row():
33
- with gr.Column():
34
- gr.HTML(title)
35
- user_info = gr.Markdown(value="", elem_id="user_info")
36
  status_display = gr.Markdown(get_geoip(), elem_id="status_display")
 
 
37
 
38
  # https://github.com/gradio-app/gradio/pull/3296
39
  def create_greeting(request: gr.Request):
@@ -54,8 +54,8 @@ with gr.Blocks(css=customCSS, theme=small_and_beautiful_theme) as demo:
54
  elem_id="user_input_tb",
55
  show_label=False, placeholder="在这里输入"
56
  ).style(container=False)
57
- with gr.Column(min_width=70, scale=1):
58
- submitBtn = gr.Button("发送", variant="primary")
59
  cancelBtn = gr.Button("取消", variant="secondary", visible=False)
60
  with gr.Row():
61
  emptyBtn = gr.Button(
 
30
  topic = gr.State("未命名对话历史记录")
31
 
32
  with gr.Row():
33
+ gr.HTML(title, elem_id="app_title")
 
 
34
  status_display = gr.Markdown(get_geoip(), elem_id="status_display")
35
+ with gr.Row(elem_id="float_display"):
36
+ user_info = gr.Markdown(value="getting user info...", elem_id="user_info")
37
 
38
  # https://github.com/gradio-app/gradio/pull/3296
39
  def create_greeting(request: gr.Request):
 
54
  elem_id="user_input_tb",
55
  show_label=False, placeholder="在这里输入"
56
  ).style(container=False)
57
+ with gr.Column(min_width=65, scale=1):
58
+ submitBtn = gr.Button("发送", variant="primary", elem_id="submit_btn")
59
  cancelBtn = gr.Button("取消", variant="secondary", visible=False)
60
  with gr.Row():
61
  emptyBtn = gr.Button(
assets/custom.css CHANGED
@@ -3,14 +3,18 @@
3
  --chatbot-color-dark: #121111;
4
  }
5
 
 
 
 
 
6
  /* 覆盖gradio的页脚信息QAQ */
7
  footer {
8
  display: none !important;
9
  }
10
- #footer{
11
  text-align: center;
12
  }
13
- #footer div{
14
  display: inline-block;
15
  }
16
  #footer .versions{
@@ -18,16 +22,34 @@ footer {
18
  opacity: 0.85;
19
  }
20
 
21
- /* user_info */
 
 
 
 
22
  #user_info {
23
  white-space: nowrap;
24
- margin-top: -1.3em !important;
25
- padding-left: 112px !important;
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
  #user_info p {
28
- font-size: .85em;
29
- font-family: monospace;
30
- color: var(--body-text-color-subdued);
 
 
 
31
  }
32
 
33
  /* status_display */
@@ -74,7 +96,7 @@ footer {
74
  overflow: hidden;
75
  }
76
  .progress {
77
- background-color: var(--block-title-background-fill);;
78
  height: 100%;
79
  border-radius: 10px;
80
  text-align: right;
@@ -139,6 +161,12 @@ ol:not(.options), ul:not(.options) {
139
  #chuanhu_chatbot .wrap {
140
  max-height: calc(100vh - 140px - var(--line-sm)*1rem - 2*var(--block-label-margin) );
141
  }
 
 
 
 
 
 
142
  }
143
  /* 对话气泡 */
144
  [class *= "message"] {
 
3
  --chatbot-color-dark: #121111;
4
  }
5
 
6
+ #app_title {
7
+ margin-top: 6px;
8
+ white-space: nowrap;
9
+ }
10
  /* 覆盖gradio的页脚信息QAQ */
11
  footer {
12
  display: none !important;
13
  }
14
+ #footer {
15
  text-align: center;
16
  }
17
+ #footer div {
18
  display: inline-block;
19
  }
20
  #footer .versions{
 
22
  opacity: 0.85;
23
  }
24
 
25
+ #float_display {
26
+ position: absolute;
27
+ max-height: 30px;
28
+ }
29
+ /* user_info */
30
  #user_info {
31
  white-space: nowrap;
32
+ position: absolute; left: 8em; top: .2em;
33
+ z-index: var(--layer-2);
34
+ box-shadow: var(--block-shadow);
35
+ border: none; border-radius: var(--block-label-radius);
36
+ background: var(--color-accent);
37
+ padding: var(--block-label-padding);
38
+ font-size: var(--block-label-text-size); line-height: var(--line-sm);
39
+ width: auto; min-height: 30px!important;
40
+ opacity: 1;
41
+ transition: opacity 0.3s ease-in-out;
42
+ }
43
+ #user_info .wrap {
44
+ opacity: 0;
45
  }
46
  #user_info p {
47
+ color: white;
48
+ font-weight: var(--block-label-text-weight);
49
+ }
50
+ #user_info.hideK {
51
+ opacity: 0;
52
+ transition: opacity 1s ease-in-out;
53
  }
54
 
55
  /* status_display */
 
96
  overflow: hidden;
97
  }
98
  .progress {
99
+ background-color: var(--block-title-background-fill);
100
  height: 100%;
101
  border-radius: 10px;
102
  text-align: right;
 
161
  #chuanhu_chatbot .wrap {
162
  max-height: calc(100vh - 140px - var(--line-sm)*1rem - 2*var(--block-label-margin) );
163
  }
164
+ [data-testid = "bot"] {
165
+ max-width: 98% !important;
166
+ }
167
+ #app_title h1{
168
+ letter-spacing: -1px; font-size: 22px;
169
+ }
170
  }
171
  /* 对话气泡 */
172
  [class *= "message"] {
assets/custom.js CHANGED
@@ -1,4 +1,5 @@
1
  // custom javascript here
 
2
  const MAX_HISTORY_LENGTH = 32;
3
 
4
  var key_down_history = [];
@@ -7,64 +8,143 @@ var user_input_ta;
7
 
8
  var ga = document.getElementsByTagName("gradio-app");
9
  var targetNode = ga[0];
10
- var observer = new MutationObserver(function(mutations) {
 
11
  for (var i = 0; i < mutations.length; i++) {
12
  if (mutations[i].addedNodes.length) {
13
- var user_input_tb = document.getElementById('user_input_tb');
14
- if (user_input_tb) {
15
- // 监听到user_input_tb被添加到DOM树中
16
- // 这里可以编写元素加载完成后需要执行的代码
17
- user_input_ta = user_input_tb.querySelector("textarea");
18
- if (user_input_ta){
19
- observer.disconnect(); // 停止监听
20
- // 在 textarea 上监听 keydown 事件
21
- user_input_ta.addEventListener("keydown", function (event) {
22
- var value = user_input_ta.value.trim();
23
- // 判断按下的是否为方向键
24
- if (event.code === 'ArrowUp' || event.code === 'ArrowDown') {
25
- // 如果按下的是方向键,且输入框中有内容,且历史记录中没有该内容,则不执行操作
26
- if(value && key_down_history.indexOf(value) === -1)
27
- return;
28
- // 对于需要响应的动作,阻止默认行为。
29
- event.preventDefault();
30
- var length = key_down_history.length;
31
- if(length === 0) {
32
- currentIndex = -1; // 如果历史记录为空,直接将当前选中的记录重置
33
- return;
34
- }
35
- if (currentIndex === -1) {
36
- currentIndex = length;
37
- }
38
- if (event.code === 'ArrowUp' && currentIndex > 0) {
39
- currentIndex--;
40
- user_input_ta.value = key_down_history[currentIndex];
41
- } else if (event.code === 'ArrowDown' && currentIndex < length - 1) {
42
- currentIndex++;
43
- user_input_ta.value = key_down_history[currentIndex];
44
- }
45
- user_input_ta.selectionStart = user_input_ta.value.length;
46
- user_input_ta.selectionEnd = user_input_ta.value.length;
47
- const input_event = new InputEvent("input", {bubbles: true, cancelable: true});
48
- user_input_ta.dispatchEvent(input_event);
49
- }else if(event.code === "Enter") {
50
- if (value) {
51
- currentIndex = -1;
52
- if(key_down_history.indexOf(value) === -1){
53
- key_down_history.push(value);
54
- if (key_down_history.length > MAX_HISTORY_LENGTH) {
55
- key_down_history.shift();
 
56
  }
57
  }
58
  }
59
- }
60
- });
61
- break;
62
  }
63
- }
64
  }
65
- }
66
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
- // 监听目标节点的子节点列表是否发生变化
69
- observer.observe(targetNode, { childList: true , subtree: true });
70
 
 
 
 
 
 
 
1
  // custom javascript here
2
+
3
  const MAX_HISTORY_LENGTH = 32;
4
 
5
  var key_down_history = [];
 
8
 
9
  var ga = document.getElementsByTagName("gradio-app");
10
  var targetNode = ga[0];
11
+
12
+ function selectHistory(mutations) {
13
  for (var i = 0; i < mutations.length; i++) {
14
  if (mutations[i].addedNodes.length) {
15
+ var user_input_tb = document.getElementById('user_input_tb');
16
+ if (user_input_tb) {
17
+ // 监听到user_input_tb被添加到DOM树中
18
+ // 这里可以编写元素加载完成后需要执行的代码
19
+ user_input_ta = user_input_tb.querySelector("textarea");
20
+ if (user_input_ta) {
21
+ observer.disconnect(); // 停止监听
22
+ // 在 textarea 上监听 keydown 事件
23
+ user_input_ta.addEventListener("keydown", function (event) {
24
+ var value = user_input_ta.value.trim();
25
+ // 判断按下的是否为方向键
26
+ if (event.code === 'ArrowUp' || event.code === 'ArrowDown') {
27
+ // 如果按下的是方向键,且输入框中有内容,且历史记录中没有该内容,则不执行操作
28
+ if (value && key_down_history.indexOf(value) === -1)
29
+ return;
30
+ // 对于需要响应的动作,阻止默认行为。
31
+ event.preventDefault();
32
+ var length = key_down_history.length;
33
+ if (length === 0) {
34
+ currentIndex = -1; // 如果历史记录为空,直接将当前选中的记录重置
35
+ return;
36
+ }
37
+ if (currentIndex === -1) {
38
+ currentIndex = length;
39
+ }
40
+ if (event.code === 'ArrowUp' && currentIndex > 0) {
41
+ currentIndex--;
42
+ user_input_ta.value = key_down_history[currentIndex];
43
+ } else if (event.code === 'ArrowDown' && currentIndex < length - 1) {
44
+ currentIndex++;
45
+ user_input_ta.value = key_down_history[currentIndex];
46
+ }
47
+ user_input_ta.selectionStart = user_input_ta.value.length;
48
+ user_input_ta.selectionEnd = user_input_ta.value.length;
49
+ const input_event = new InputEvent("input", { bubbles: true, cancelable: true });
50
+ user_input_ta.dispatchEvent(input_event);
51
+ } else if (event.code === "Enter") {
52
+ if (value) {
53
+ currentIndex = -1;
54
+ if (key_down_history.indexOf(value) === -1) {
55
+ key_down_history.push(value);
56
+ if (key_down_history.length > MAX_HISTORY_LENGTH) {
57
+ key_down_history.shift();
58
+ }
59
  }
60
  }
61
  }
62
+ });
63
+ break;
64
+ }
65
  }
 
66
  }
67
+ }
68
+ }
69
+ var userInfoDiv = null;
70
+ function toggleUserInfoVisibility(shouldHide) {
71
+ if (userInfoDiv) {
72
+ if (shouldHide) {
73
+ userInfoDiv.classList.add("hideK");
74
+ } else {
75
+ userInfoDiv.classList.remove("hideK");
76
+ }
77
+ }
78
+ }
79
+ function showOrHideUserInfo() {
80
+ userInfoDiv = document.getElementById("user_info");
81
+ var appTitleDiv = document.getElementById("app_title");
82
+ var sendBtn = document.getElementById("submit_btn");
83
+
84
+ // Bind mouse/touch events to show/hide user info
85
+ appTitleDiv.addEventListener("mouseenter", function () {
86
+ toggleUserInfoVisibility(false);
87
+ });
88
+ userInfoDiv.addEventListener("mouseenter", function () {
89
+ toggleUserInfoVisibility(false);
90
+ });
91
+ sendBtn.addEventListener("mouseenter", function () {
92
+ toggleUserInfoVisibility(false);
93
+ });
94
+
95
+ appTitleDiv.addEventListener("mouseleave", function () {
96
+ toggleUserInfoVisibility(true);
97
+ });
98
+ userInfoDiv.addEventListener("mouseleave", function () {
99
+ toggleUserInfoVisibility(true);
100
+ });
101
+ sendBtn.addEventListener("mouseleave", function () {
102
+ toggleUserInfoVisibility(true);
103
+ });
104
+
105
+ appTitleDiv.ontouchstart = function () {
106
+ toggleUserInfoVisibility(false);
107
+ };
108
+ userInfoDiv.ontouchstart = function () {
109
+ toggleUserInfoVisibility(false);
110
+ };
111
+ sendBtn.ontouchstart = function () {
112
+ toggleUserInfoVisibility(false);
113
+ };
114
+
115
+ appTitleDiv.ontouchend = function () {
116
+ setTimeout(function () {
117
+ toggleUserInfoVisibility(true);
118
+ }, 3000);
119
+ };
120
+ userInfoDiv.ontouchend = function () {
121
+ setTimeout(function () {
122
+ toggleUserInfoVisibility(true);
123
+ }, 3000);
124
+ };
125
+ sendBtn.ontouchend = function () {
126
+ setTimeout(function () {
127
+ toggleUserInfoVisibility(true);
128
+ }, 3000); // Delay 1 second to hide user info
129
+ };
130
+
131
+ // Hide user info after 2 second
132
+ setTimeout(function () {
133
+ toggleUserInfoVisibility(true);
134
+ }, 2000);
135
+ }
136
+
137
+
138
+ var observer = new MutationObserver(function (mutations) {
139
+ selectHistory(mutations);
140
+ showOrHideUserInfo();
141
+ }
142
+ );
143
+ observer.observe(targetNode, { childList: true, subtree: true });
144
 
 
 
145
 
146
+ window.addEventListener("DOMContentLoaded", function () {
147
+ setTimeout(function () {
148
+ showOrHideUserInfo();
149
+ }, 2000);
150
+ });
modules/presets.py CHANGED
@@ -30,7 +30,7 @@ CONCURRENT_COUNT = 100 # 允许同时使用的用户数量
30
  SIM_K = 5
31
  INDEX_QUERY_TEMPRATURE = 1.0
32
 
33
- title = """<h1 align="left" style="min-width:200px; margin-top:6px; white-space: nowrap;">川虎ChatGPT 🚀</h1>"""
34
  description = """\
35
  <div align="center" style="margin:16px 0">
36
 
@@ -42,9 +42,7 @@ description = """\
42
  </div>
43
  """
44
 
45
- footer = """\
46
- <div class="versions">{versions}</div>
47
- """
48
 
49
  summarize_prompt = "你是谁?我们刚才聊了什么?" # 总结对话时的 prompt
50
 
 
30
  SIM_K = 5
31
  INDEX_QUERY_TEMPRATURE = 1.0
32
 
33
+ title = """<h1 align="left">川虎ChatGPT 🚀</h1>"""
34
  description = """\
35
  <div align="center" style="margin:16px 0">
36
 
 
42
  </div>
43
  """
44
 
45
+ footer = """<div class="versions">{versions}</div>"""
 
 
46
 
47
  summarize_prompt = "你是谁?我们刚才聊了什么?" # 总结对话时的 prompt
48