fix(ui): allow Control UI chat without node

This commit is contained in:
Peter Steinberger
2026-01-04 16:46:39 +00:00
parent 564cc9359d
commit 266fd748d0
3 changed files with 9 additions and 32 deletions

View File

@@ -183,16 +183,7 @@ export function renderApp(state: AppViewState) {
const presenceCount = state.presenceEntries.length; const presenceCount = state.presenceEntries.length;
const sessionsCount = state.sessionsResult?.count ?? null; const sessionsCount = state.sessionsResult?.count ?? null;
const cronNext = state.cronStatus?.nextWakeAtMs ?? null; const cronNext = state.cronStatus?.nextWakeAtMs ?? null;
const hasConnectedMobileNode = state.nodes.some((n) => { const chatDisabledReason = state.connected ? null : "Disconnected from gateway.";
if (!Boolean(n.connected)) return false;
const p = typeof n.platform === "string" ? n.platform.trim().toLowerCase() : "";
return p.startsWith("ios") || p.startsWith("ipados") || p.startsWith("android");
});
const chatDisabledReason = !state.connected
? "Disconnected from gateway."
: hasConnectedMobileNode
? null
: "No connected iOS/Android node — Web Chat + Talk are disabled.";
return html` return html`
<div class="shell"> <div class="shell">
@@ -398,7 +389,7 @@ export function renderApp(state: AppViewState) {
stream: state.chatStream, stream: state.chatStream,
draft: state.chatMessage, draft: state.chatMessage,
connected: state.connected, connected: state.connected,
canSend: state.connected && hasConnectedMobileNode, canSend: state.connected,
disabledReason: chatDisabledReason, disabledReason: chatDisabledReason,
sessions: state.sessionsResult, sessions: state.sessionsResult,
onRefresh: () => { onRefresh: () => {

View File

@@ -451,17 +451,6 @@ export class ClawdbotApp extends LitElement {
this.nodesPollInterval = null; this.nodesPollInterval = null;
} }
private hasConnectedMobileNode() {
return this.nodes.some((n) => {
if (!Boolean(n.connected)) return false;
const p =
typeof n.platform === "string" ? n.platform.trim().toLowerCase() : "";
return (
p.startsWith("ios") || p.startsWith("ipados") || p.startsWith("android")
);
});
}
resetToolStream() { resetToolStream() {
this.toolStreamById.clear(); this.toolStreamById.clear();
this.toolStreamOrder = []; this.toolStreamOrder = [];
@@ -765,9 +754,8 @@ export class ClawdbotApp extends LitElement {
async loadCron() { async loadCron() {
await Promise.all([loadCronStatus(this), loadCronJobs(this)]); await Promise.all([loadCronStatus(this), loadCronJobs(this)]);
} }
async handleSendChat() { async handleSendChat() {
if (!this.connected || !this.hasConnectedMobileNode()) return; if (!this.connected) return;
await sendChat(this); await sendChat(this);
void loadChatHistory(this); void loadChatHistory(this);
} }

View File

@@ -23,13 +23,11 @@ export type ChatProps = {
export function renderChat(props: ChatProps) { export function renderChat(props: ChatProps) {
const canInteract = props.connected; const canInteract = props.connected;
const canCompose = props.canSend && !props.sending; const canCompose = props.connected && !props.sending;
const sessionOptions = resolveSessionOptions(props.sessionKey, props.sessions); const sessionOptions = resolveSessionOptions(props.sessionKey, props.sessions);
const composePlaceholder = (() => { const composePlaceholder = props.connected
if (!props.connected) return "Connect to the gateway to start chatting…"; ? "Message (⌘↩ to send)"
if (!props.canSend) return "Connect an iOS/Android node to enable Web Chat + Talk…"; : "Connect to the gateway to start chatting…";
return "Message (⌘↩ to send)";
})();
return html` return html`
<section class="card chat"> <section class="card chat">
@@ -90,7 +88,7 @@ export function renderChat(props: ChatProps) {
<span>Message</span> <span>Message</span>
<textarea <textarea
.value=${props.draft} .value=${props.draft}
?disabled=${!props.canSend} ?disabled=${!props.connected}
@keydown=${(e: KeyboardEvent) => { @keydown=${(e: KeyboardEvent) => {
if (e.key !== "Enter") return; if (e.key !== "Enter") return;
if (!e.metaKey && !e.ctrlKey) return; if (!e.metaKey && !e.ctrlKey) return;
@@ -105,7 +103,7 @@ export function renderChat(props: ChatProps) {
<div class="row chat-compose__actions"> <div class="row chat-compose__actions">
<button <button
class="btn primary" class="btn primary"
?disabled=${!props.canSend || props.sending} ?disabled=${!props.connected || props.sending}
@click=${props.onSend} @click=${props.onSend}
> >
${props.sending ? "Sending…" : "Send"} ${props.sending ? "Sending…" : "Send"}