Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions packages/live2d/src/components/Live2dChatWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
private chatApi: ChatApi | null = null;
private historyMessages: ChatMessage[] = [];
private _hidePopoverTimer?: number;
private _chatRequestSeq = 0;

connectedCallback(): void {
super.connectedCallback();
Expand All @@ -83,8 +84,9 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
? "pointer-events-auto opacity-100"
: "pointer-events-none opacity-0",
].join(" ");
const sendButtonClass =
this._canSend && !this._isLoading
const sendButtonClass = this._isLoading
? "bg-[#f97373] text-white shadow-[0_6px_16px_rgba(249,115,115,0.25)] hover:bg-[#ef4444]"
: this._canSend
? "bg-[#ffab5c] text-white shadow-[0_6px_16px_rgba(255,171,92,0.25)] hover:bg-[#ff9840]"
: "bg-[#eee7de] text-slate-400 cursor-not-allowed";

Expand All @@ -109,13 +111,13 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
type="button"
class="inline-flex h-8 w-8 flex-none items-center justify-center rounded-full border-none transition-colors ${sendButtonClass}"
@click=${this.handleSend}
aria-label=${this._isLoading ? "发送中" : "发送消息"}
aria-label=${this._isLoading ? "停止生成" : "发送消息"}
>
${
this._isLoading
? html`<iconify-icon
id="loadingIcon"
icon="line-md:loading-twotone-loop"
id="stop"
icon="mingcute:stop-fill"
width="18"
height="18"
class="text-current"
Expand Down Expand Up @@ -176,11 +178,23 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
};

handleSend = (): void => {
if (this._canSend && !this._isLoading) {
if (this._isLoading) {
this.stopMessage();
return;
}
if (this._canSend) {
void this.sendMessage();
}
};

private stopMessage(): void {
this._chatRequestSeq += 1;
this.chatApi?.abort();
this._isLoading = false;
this._canSend = !!this._input?.value.length;
this.focusInput();
}

private async sendMessage(): Promise<void> {
if (!this._input || !this._input.value || this._isLoading) {
return;
Expand All @@ -195,17 +209,20 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
this._canSend = false;
this._isLoading = true;
this.focusInput();
const requestSeq = ++this._chatRequestSeq;

try {
await this.sendChatMessage(message, this.readStoredHistoryMessages());
} catch (error) {
console.error("[Live2dChatWindow] Send message error:", error);
} finally {
this._isLoading = false;
if (this._input) {
this._canSend = this._input.value.length > 0;
if (requestSeq === this._chatRequestSeq) {
this._isLoading = false;
if (this._input) {
this._canSend = this._input.value.length > 0;
}
this.focusInput();
}
this.focusInput();
}
}

Expand Down Expand Up @@ -273,6 +290,7 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
this._isLoading = true;
this._canSend = false;
this.focusInput();
const requestSeq = ++this._chatRequestSeq;
try {
await this.sendChatMessage(resume.message, resume.historyMessages);
} catch (error) {
Expand All @@ -281,11 +299,13 @@ export class Live2dChatWindow extends DraggableUnoLitElement {
error,
);
} finally {
this._isLoading = false;
if (this._input) {
this._canSend = this._input.value.length > 0;
if (requestSeq === this._chatRequestSeq) {
this._isLoading = false;
if (this._input) {
this._canSend = this._input.value.length > 0;
}
this.focusInput();
}
this.focusInput();
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/main/java/run/halo/live2d/Live2dSettingProcess.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public class Live2dSettingProcess implements Live2dSetting {
private static final List<String> TIPS_FIELDS = List.of(
"firstOpenSite", "backSite", "backSiteTip", "copyContent", "copyContentTip",
"openConsole", "openConsoleTip", "selectorTips", "tipsPath");
private static final List<String> ADVANCED_FIELDS = List.of(
"consoleShowStatu", "photoName", "live2dLocation");
private static final List<String> ADVANCED_FIELDS = List.of("consoleShowStatu", "photoName");
private static final List<String> AI_CHAT_PUBLIC_FIELDS = List.of(
"chunkTimeout", "showChatMessageTimeout", "autoContinuationMessageMinVisibleMs",
"requestAcceptedMessage", "reasoningMessages", "reasoningMessageInterval",
Expand Down
46 changes: 32 additions & 14 deletions src/main/resources/extensions/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,18 @@ spec:
label: 打开控制台提示语
name: openConsoleTip
value: "你是想要看看我的小秘密吗?"
- $formkit: repeater
- $formkit: array
name: selectorTips
label: 选择器提示语
help: 根据 CSS 选择器自定义 Live2d 呈现的文本(各主题选择器可能不同)。
value: []
addLabel: 添加选择器提示语
emptyText: 暂无选择器提示语
itemLabels:
- type: text
label: $value.mouseAction
- type: text
label: $value.selector
children:
- $formkit: select
name: mouseAction
Expand All @@ -136,12 +143,17 @@ spec:
name: selector
label: CSS 选择器
validation: required
- $formkit: repeater
- $formkit: array
name: messageTexts
label: 提示语集合
help: 可以填写多个提示语,Live2d 将会随机选择一个
min: 1
value: []
addLabel: 添加提示语
emptyText: 暂无提示语
itemLabels:
- type: text
label: $value.message
children:
- $formkit: text
name: message
Expand Down Expand Up @@ -234,11 +246,16 @@ spec:
name: requestAcceptedMessage
help: 用户发送消息后,Live2D 会立刻展示这条提示语,减少等待时的空白感
validation: String
- $formkit: repeater
- $formkit: array
label: 思考中提示语
name: reasoningMessages
help: 当模型正在返回思考内容但还没有可展示回复时,Live2D 会随机展示其中一条。思考时间较长时会自动切换
min: 1
addLabel: 添加思考提示语
emptyText: 暂无思考提示语
itemLabels:
- type: text
label: $value.message
children:
- $formkit: text
name: message
Expand Down Expand Up @@ -317,11 +334,16 @@ spec:
allowedExternalOrigins: []
allowNewTab: false
children:
- $formkit: repeater
- $formkit: array
name: allowedExternalOrigins
label: 允许打开的外部站点
help: 仅填写 origin,例如 https://github.com。外链仍会默认请求访客确认。
value: []
addLabel: 添加外部站点
emptyText: 暂无外部站点
itemLabels:
- type: text
label: $value.origin
children:
- $formkit: text
name: origin
Expand Down Expand Up @@ -365,11 +387,16 @@ spec:
maxResponseChars: 4000
timeoutSeconds: 5
children:
- $formkit: repeater
- $formkit: array
name: allowedOrigins
label: 允许访问的 Origin
help: 仅填写可信公网 Origin,例如 https://api.example.com。不会跟随重定向,也不会访问 localhost、内网或链路本地地址。
value: []
addLabel: 添加 Origin
emptyText: 暂无 Origin
itemLabels:
- type: text
label: $value.origin
children:
- $formkit: text
name: origin
Expand Down Expand Up @@ -414,15 +441,6 @@ spec:
name: photoName
validation: required
value: live2d
- $formkit: select
label: 看板娘位置
name: live2dLocation
value: left
options:
- value: left
label: 屏幕左侧
- value: right
label: 屏幕右侧
- $formkit: select
help: 页面何时加载 Live2d。网站带宽有限时,可选择优先加载页面全部内容再加载 Live2d。
label: Live2d 加载时机
Expand Down