Spaces:
Sleeping
Sleeping
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
- ChuanhuChatbot.py +5 -5
- assets/custom.css +37 -9
- assets/custom.js +132 -52
- 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 |
-
|
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=
|
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 |
-
|
|
|
|
|
|
|
|
|
22 |
#user_info {
|
23 |
white-space: nowrap;
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
}
|
27 |
#user_info p {
|
28 |
-
|
29 |
-
font-
|
30 |
-
|
|
|
|
|
|
|
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 |
-
|
|
|
11 |
for (var i = 0; i < mutations.length; i++) {
|
12 |
if (mutations[i].addedNodes.length) {
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
56 |
}
|
57 |
}
|
58 |
}
|
59 |
-
}
|
60 |
-
|
61 |
-
|
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"
|
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 |
|