feat: enhance BlueBubbles message actions with support for message editing, reply metadata, and improved effect handling

This commit is contained in:
Tyler Yust
2026-01-19 23:40:22 -08:00
committed by Peter Steinberger
parent 2e6c58bf75
commit 574b848863
22 changed files with 1366 additions and 83 deletions

View File

@@ -345,6 +345,15 @@
align-items: center;
}
.config-form .field.checkbox {
grid-template-columns: 18px minmax(0, 1fr);
column-gap: 10px;
}
.config-form .field.checkbox input[type="checkbox"] {
margin: 0;
}
.form-grid {
display: grid;
gap: 12px;

View File

@@ -215,7 +215,9 @@ function renderGenericAccount(account: ChannelAccountSnapshot) {
</div>
<div>
<span class="label">Connected</span>
<span>${account.connected ? "Yes" : "No"}</span>
<span>
${account.connected == null ? "n/a" : account.connected ? "Yes" : "No"}
</span>
</div>
<div>
<span class="label">Last inbound</span>

View File

@@ -99,6 +99,55 @@ export function renderNode(params: {
</label>
`;
}
const primitiveTypes = new Set(
nonNull
.map((variant) => schemaType(variant))
.filter((variant): variant is string => Boolean(variant)),
);
const normalizedTypes = new Set(
[...primitiveTypes].map((variant) => (variant === "integer" ? "number" : variant)),
);
const primitiveOnly = [...normalizedTypes].every((variant) =>
["string", "number", "boolean"].includes(variant),
);
if (primitiveOnly && normalizedTypes.size > 0) {
const hasString = normalizedTypes.has("string");
const hasNumber = normalizedTypes.has("number");
const hasBoolean = normalizedTypes.has("boolean");
if (hasBoolean && normalizedTypes.size === 1) {
return renderNode({
...params,
schema: { ...schema, type: "boolean", anyOf: undefined, oneOf: undefined },
});
}
if (hasString || hasNumber) {
const displayValue = value ?? schema.default ?? "";
return html`
<label class="field">
${showLabel ? html`<span>${label}</span>` : nothing}
${help ? html`<div class="muted">${help}</div>` : nothing}
<input
type=${hasNumber && !hasString ? "number" : "text"}
.value=${displayValue == null ? "" : String(displayValue)}
?disabled=${disabled}
@input=${(e: Event) => {
const raw = (e.target as HTMLInputElement).value;
if (hasString || !hasNumber || raw.trim() === "" || /[^0-9-.]/.test(raw)) {
onPatch(path, raw === "" ? undefined : raw);
return;
}
const parsed = Number(raw);
onPatch(path, Number.isNaN(parsed) ? raw : parsed);
}}
/>
</label>
`;
}
}
}
if (schema.enum) {
@@ -254,9 +303,7 @@ export function renderNode(params: {
? schema.default
: false;
return html`
<label class="field">
${showLabel ? html`<span>${label}</span>` : nothing}
${help ? html`<div class="muted">${help}</div>` : nothing}
<label class="field checkbox">
<input
type="checkbox"
.checked=${displayValue}
@@ -264,6 +311,12 @@ export function renderNode(params: {
@change=${(e: Event) =>
onPatch(path, (e.target as HTMLInputElement).checked)}
/>
${showLabel ? html`<span>${label}</span>` : nothing}
${help
? html`<div class="muted" style="grid-column: 1 / -1;">
${help}
</div>`
: nothing}
</label>
`;
}