feat: Answer or reject inbound calls from menu (#2620)

- For: #2587
This commit is contained in:
Dermot Duffy
2026-07-26 14:24:14 -07:00
committed by GitHub
parent ababe133a8
commit 0f8593f9fa
7 changed files with 120 additions and 34 deletions
+34 -10
View File
@@ -19,6 +19,7 @@ import type { HomeAssistant } from '../ha/types';
import { localize } from '../localize/localize.js';
import type { MediaLoadedInfo } from '../types';
import {
createCallAnswerAction,
createCallEndAction,
createCallStartAction,
createCameraAction,
@@ -507,15 +508,26 @@ export class MenuButtonController {
return null;
}
// In a call: a single hang-up button, regardless of target count.
if (callManager?.isActive()) {
// In a call, a single button regardless of target count. An unanswered
// inbound call (ringing) answers; an answered or outbound call hangs up.
const call = callManager?.getCall();
if (call) {
const ringing = call.inbound && !call.answered;
return {
icon: 'mdi:phone-hangup',
title: localize('config.live.controls.call.end'),
style: this._getEmphasizedStyle(true),
icon: ringing ? 'mdi:phone-ring' : 'mdi:phone-hangup',
title: ringing
? localize('config.live.controls.call.answer')
: localize('config.live.controls.call.end'),
style: ringing
? this._getPulsingStyle(
'var(--advanced-camera-card-menu-button-positive-color)',
)
: this._getEmphasizedStyle(true),
...config.menu.buttons.call,
type: 'custom:advanced-camera-card-menu-icon',
tap_action: createCallEndAction(),
tap_action: ringing ? createCallAnswerAction() : createCallEndAction(),
// While ringing, tap answers and hold rejects.
...(ringing && { hold_action: createCallEndAction() }),
};
}
@@ -915,16 +927,28 @@ export class MenuButtonController {
*/
private _getEmphasizedStyle(critical?: boolean): StyleInfo {
if (critical) {
return {
animation: 'pulse 3s infinite',
color: 'var(--advanced-camera-card-menu-button-critical-color)',
};
return this._getPulsingStyle(
'var(--advanced-camera-card-menu-button-critical-color)',
);
}
return {
color: 'var(--advanced-camera-card-menu-button-active-color)',
};
}
/**
* Get a pulsing style in the given color, e.g. to draw attention to a
* critical or a ringing button.
* @param color The CSS color to pulse.
* @returns A StyleInfo.
*/
private _getPulsingStyle(color: string): StyleInfo {
return {
animation: 'pulse 3s infinite',
color,
};
}
/**
* Given a button determine if the style should be emphasized by examining all
* of the actions sequentially.
+16
View File
@@ -141,3 +141,19 @@ div.opposing {
// Further theme related styling is dynamically applied by `menu.ts`, see
// `_renderPerInstanceStyle`.
/*****************
* Pulse animation
*****************/
// Referenced by the inline `animation` on emphasized button styles in
// `menu-button-controller` (e.g. the ringing call button).
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
+5
View File
@@ -105,6 +105,11 @@
var(--advanced-camera-card-warning-color)
);
// The color of a positive icon in the menu (e.g. answer an inbound call).
--advanced-camera-card-menu-button-positive-color: var(
--advanced-camera-card-success-color
);
// The background color of the button "circles" in the menu.
--advanced-camera-card-menu-button-background: color-mix(
in oklab,