Keep Lovelace cast active, remove media app

This commit is contained in:
Bram Kragten 2021-11-04 16:31:19 +01:00
parent 3fd0becfd4
commit 369d0538d1
No known key found for this signature in database
GPG Key ID: FBE2DFDB363EF55B
3 changed files with 54 additions and 115 deletions

View File

@ -1,18 +1,26 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script> <head>
<script type="module" src="<%= latestReceiverJS %>"></script> <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
<%= renderTemplate('_style_base') %> <script type="module" src="<%= latestReceiverJS %>"></script>
<style> <%= renderTemplate('_style_base') %>
body { <style>
background-color: white; body {
font-size: initial; background-color: white;
} font-size: initial;
</style> }
<script> .castMediaElement {
var _gaq=[['_setAccount','UA-57927901-10'],['_trackPageview']]; display: none;
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0]; }
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js'; </style>
s.parentNode.insertBefore(g,s)}(document,'script')); <script>
</script> var _gaq=[['_setAccount','UA-57927901-10'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</head>
<body>
<video class="castMediaElement"></video>
</body>
</html> </html>

View File

@ -9,129 +9,55 @@ import { ReceivedMessage } from "./types";
const lovelaceController = new HcMain(); const lovelaceController = new HcMain();
document.body.append(lovelaceController); document.body.append(lovelaceController);
const mediaPlayer = document.createElement("cast-media-player"); const removeTouchControls = () => {
mediaPlayer.style.display = "none";
document.body.append(mediaPlayer);
const playerStylesAdded = false;
let controls: HTMLElement | null;
const setTouchControlsVisibility = (visible: boolean) => {
if (!castContext.getDeviceCapabilities().touch_input_supported) { if (!castContext.getDeviceCapabilities().touch_input_supported) {
return; return;
} }
controls = const controls = document.body.querySelector(
controls || "touch-controls"
(document.body.querySelector("touch-controls") as HTMLElement | null); ) as HTMLElement | null;
if (controls) { if (controls) {
controls.style.display = visible ? "initial" : "none"; controls.remove();
} }
};
const showLovelaceController = () => {
mediaPlayer.style.display = "none";
lovelaceController.style.display = "initial";
document.body.setAttribute("style", "overflow-y: auto !important"); document.body.setAttribute("style", "overflow-y: auto !important");
setTouchControlsVisibility(false);
}; };
const showMediaPlayer = () => { const playMedia = () => {
lovelaceController.style.display = "none"; const playerManager = castContext.getPlayerManager();
mediaPlayer.style.display = "initial"; const loadRequestData = new cast.framework.messages.LoadRequestData();
document.body.removeAttribute("style"); loadRequestData.autoplay = true;
setTouchControlsVisibility(true); loadRequestData.media = new cast.framework.messages.MediaInformation();
if (!playerStylesAdded) { loadRequestData.media.contentId =
const style = document.createElement("style"); "https://www.home-assistant.io/images/blog/2018-09-thinking-big/social.png";
style.innerHTML = ` loadRequestData.media.contentType = "image/jpeg";
body { loadRequestData.media.streamType = cast.framework.messages.StreamType.NONE;
--logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg'); const metadata = new cast.framework.messages.GenericMediaMetadata();
--logo-repeat: no-repeat; metadata.title = "Home Assistant Lovelace";
--playback-logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg'); loadRequestData.media.metadata = metadata;
--theme-hue: 200;
--progress-color: #03a9f4; loadRequestData.requestId = 0;
--splash-image: url('https://home-assistant.io/images/cast/splash.png'); playerManager.load(loadRequestData);
--splash-size: cover;
}
`;
document.head.appendChild(style);
}
}; };
const options = new cast.framework.CastReceiverOptions(); const options = new cast.framework.CastReceiverOptions();
options.disableIdleTimeout = true; options.disableIdleTimeout = true;
// @ts-ignore
options.skipPlayersLoad = true;
options.customNamespaces = { options.customNamespaces = {
[CAST_NS]: cast.framework.system.MessageType.JSON, [CAST_NS]: cast.framework.system.MessageType.JSON,
}; };
// The docs say we need to set options.touchScreenOptimizeApp = true
// https://developers.google.com/cast/docs/caf_receiver/customize_ui#accessing_ui_controls
// This doesn't work.
// @ts-ignore
options.touchScreenOptimizedApp = true;
// The class reference say we can set a uiConfig in options to set it
// https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.CastReceiverOptions#uiConfig
// This doesn't work either.
// @ts-ignore
options.uiConfig = new cast.framework.ui.UiConfig();
// @ts-ignore
options.uiConfig.touchScreenOptimizedApp = true;
castContext.setInactivityTimeout(86400); // 1 day
castContext.addCustomMessageListener( castContext.addCustomMessageListener(
CAST_NS, CAST_NS,
// @ts-ignore // @ts-ignore
(ev: ReceivedMessage<HassMessage>) => { (ev: ReceivedMessage<HassMessage>) => {
// We received a show Lovelace command, stop media from playing, hide media player and show Lovelace controller // Remove touch controls, so touch can be used
if ( removeTouchControls();
playerManager.getPlayerState() !==
cast.framework.messages.PlayerState.IDLE
) {
playerManager.stop();
} else {
showLovelaceController();
}
const msg = ev.data; const msg = ev.data;
msg.senderId = ev.senderId; msg.senderId = ev.senderId;
lovelaceController.processIncomingMessage(msg); lovelaceController.processIncomingMessage(msg);
} // Play media so the media state will not be idle, to prevent the app from getting closed
); playMedia();
const playerManager = castContext.getPlayerManager();
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
(loadRequestData) => {
// We received a play media command, hide Lovelace and show media player
showMediaPlayer();
const media = loadRequestData.media;
// Special handling if it came from Google Assistant
if (media.entity) {
media.contentId = media.entity;
media.streamType = cast.framework.messages.StreamType.LIVE;
media.contentType = "application/vnd.apple.mpegurl";
// @ts-ignore
media.hlsVideoSegmentFormat =
cast.framework.messages.HlsVideoSegmentFormat.FMP4;
}
return loadRequestData;
}
);
playerManager.addEventListener(
cast.framework.events.EventType.MEDIA_STATUS,
(event) => {
if (
event.mediaStatus?.playerState ===
cast.framework.messages.PlayerState.IDLE &&
event.mediaStatus?.idleReason &&
event.mediaStatus?.idleReason !==
cast.framework.messages.IdleReason.INTERRUPTED
) {
// media finished or stopped, return to default Lovelace
showLovelaceController();
}
} }
); );

View File

@ -107,6 +107,7 @@ export class HcMain extends HassElement {
this._sendStatus(); this._sendStatus();
} }
}); });
this.addEventListener("dialog-closed", this._dialogClosed);
} }
private _sendStatus(senderId?: string) { private _sendStatus(senderId?: string) {
@ -131,6 +132,10 @@ export class HcMain extends HassElement {
} }
} }
private _dialogClosed = () => {
document.body.setAttribute("style", "overflow-y: auto !important");
};
private async _handleGetStatusMessage(msg: GetStatusMessage) { private async _handleGetStatusMessage(msg: GetStatusMessage) {
this._sendStatus(msg.senderId!); this._sendStatus(msg.senderId!);
} }