-
Notifications
You must be signed in to change notification settings - Fork 118
Expand file tree
/
Copy pathChatHtml.java
More file actions
104 lines (93 loc) · 4.93 KB
/
ChatHtml.java
File metadata and controls
104 lines (93 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package ai.javaclaw.chat;
import org.springframework.web.util.HtmlUtils;
import java.util.List;
/**
* Chat message bubble HTML fragment helpers.
*/
public class ChatHtml {
private ChatHtml() {}
public static String agentBubble(String text) {
return """
<article class="ar-msg ar-msg--agent">\
<div class="ar-msg__avatar">JC</div>\
<div class="ar-msg__bubble">%s</div>\
</article>""".formatted(HtmlUtils.htmlEscape(text));
}
public static String userBubble(String text) {
return """
<article class="ar-msg ar-msg--user">\
<div class="ar-msg__bubble">%s</div>\
</article>""".formatted(HtmlUtils.htmlEscape(text));
}
public static String typingDots() {
return """
<div class="ar-typing">\
<div class="ar-msg__avatar">JC</div>\
<div class="ar-typing__dots"><span></span><span></span><span></span></div>\
</div>""";
}
public static String chatInputArea(String agentId, String conversationId) {
if ("web".equals(conversationId)) {
return """
<form id="chat-form" ws-send hx-boost="false"
hx-vals='js:{"type": "userMessage", "agentId": document.getElementById("agent-select") ? document.getElementById("agent-select").value : "%s", "conversationId": document.getElementById("channel-select") ? document.getElementById("channel-select").value : "web"}'>
<div class="field is-grouped" style="align-items: flex-end; margin: 0;">
<div class="control is-expanded">
<textarea id="message-input" class="textarea" name="message" rows="1"
placeholder="Message JavaClaw\u2026"
autocomplete="off" spellcheck="true" autofocus
hx-trigger="keydown[key=='Enter'&&!shiftKey] consume"
ws-send></textarea>
</div>
<div class="control">
<button id="send-btn" type="submit" class="button is-primary" title="Send (Enter)">
<span class="icon">
<svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true">
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
</svg>
</span>
</button>
</div>
</div>
</form>""".formatted(HtmlUtils.htmlEscape(agentId));
}
String label = HtmlUtils.htmlEscape(labelFor(conversationId));
return """
<p class="chat-readonly-notice">This is a read-only view of <strong>%s</strong>. \
Open %s to continue the conversation.</p>""".formatted(label, label);
}
public static String conversationSelector(List<String> ids, String selectedId) {
StringBuilder sb = new StringBuilder();
sb.append("""
<select id="channel-select" class="select" name="conversationId" \
ws-send hx-trigger="change" \
hx-vals='js:{"type": "channelChanged", "agentId": document.getElementById("agent-select") ? document.getElementById("agent-select").value : ""}'>""");
for (String id : ids) {
sb.append("<option value=\"").append(HtmlUtils.htmlEscape(id)).append("\"");
if (id.equals(selectedId)) sb.append(" selected");
sb.append(">").append(HtmlUtils.htmlEscape(labelFor(id))).append("</option>");
}
sb.append("</select>");
return sb.toString();
}
public static String agentSelector(List<String> ids, String selectedId) {
StringBuilder sb = new StringBuilder();
sb.append("""
<select id="agent-select" class="select" name="agentId" \
ws-send hx-trigger="change" \
hx-vals='{"type": "agentChanged"}'>""");
for (String id : ids) {
sb.append("<option value=\"").append(HtmlUtils.htmlEscape(id)).append("\"");
if (id.equals(selectedId)) sb.append(" selected");
sb.append(">").append(HtmlUtils.htmlEscape(id)).append("</option>");
}
sb.append("</select>");
return sb.toString();
}
private static String labelFor(String conversationId) {
if ("web".equals(conversationId)) return "Web Chat";
if (conversationId.startsWith("discord-")) return "Discord (" + conversationId.substring("discord-".length()) + ")";
if (conversationId.startsWith("telegram-")) return "Telegram (" + conversationId.substring("telegram-".length()) + ")";
return conversationId;
}
}