frontend.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """"Starting setup task: Frontend"."""
  2. from __future__ import annotations
  3. from typing import TYPE_CHECKING
  4. from aiohttp import web
  5. from homeassistant.components.http import HomeAssistantView
  6. from homeassistant.core import HomeAssistant, callback
  7. from .const import DOMAIN
  8. from .hacs_frontend import locate_dir, VERSION as FE_VERSION
  9. from .hacs_frontend_experimental import (
  10. locate_dir as experimental_locate_dir,
  11. VERSION as EXPERIMENTAL_FE_VERSION,
  12. )
  13. URL_BASE = "/hacsfiles"
  14. if TYPE_CHECKING:
  15. from .base import HacsBase
  16. @callback
  17. def async_register_frontend(hass: HomeAssistant, hacs: HacsBase) -> None:
  18. """Register the frontend."""
  19. # Register themes
  20. hass.http.register_static_path(f"{URL_BASE}/themes", hass.config.path("themes"))
  21. # Register frontend
  22. if hacs.configuration.frontend_repo_url:
  23. hacs.log.warning(
  24. "<HacsFrontend> Frontend development mode enabled. Do not run in production!"
  25. )
  26. hass.http.register_view(HacsFrontendDev())
  27. elif hacs.configuration.experimental:
  28. hacs.log.info("<HacsFrontend> Using experimental frontend")
  29. hass.http.register_static_path(
  30. f"{URL_BASE}/frontend", experimental_locate_dir(), cache_headers=False
  31. )
  32. else:
  33. #
  34. hass.http.register_static_path(f"{URL_BASE}/frontend", locate_dir(), cache_headers=False)
  35. # Custom iconset
  36. hass.http.register_static_path(
  37. f"{URL_BASE}/iconset.js", str(hacs.integration_dir / "iconset.js")
  38. )
  39. if "frontend_extra_module_url" not in hass.data:
  40. hass.data["frontend_extra_module_url"] = set()
  41. hass.data["frontend_extra_module_url"].add(f"{URL_BASE}/iconset.js")
  42. # Register www/community for all other files
  43. use_cache = hacs.core.lovelace_mode == "storage"
  44. hacs.log.info(
  45. "<HacsFrontend> %s mode, cache for /hacsfiles/: %s",
  46. hacs.core.lovelace_mode,
  47. use_cache,
  48. )
  49. hass.http.register_static_path(
  50. URL_BASE,
  51. hass.config.path("www/community"),
  52. cache_headers=use_cache,
  53. )
  54. hacs.frontend_version = (
  55. FE_VERSION if not hacs.configuration.experimental else EXPERIMENTAL_FE_VERSION
  56. )
  57. # Add to sidepanel if needed
  58. if DOMAIN not in hass.data.get("frontend_panels", {}):
  59. hass.components.frontend.async_register_built_in_panel(
  60. component_name="custom",
  61. sidebar_title=hacs.configuration.sidepanel_title,
  62. sidebar_icon=hacs.configuration.sidepanel_icon,
  63. frontend_url_path=DOMAIN,
  64. config={
  65. "_panel_custom": {
  66. "name": "hacs-frontend",
  67. "embed_iframe": True,
  68. "trust_external": False,
  69. "js_url": f"/hacsfiles/frontend/entrypoint.js?hacstag={hacs.frontend_version}",
  70. }
  71. },
  72. require_admin=True,
  73. )
  74. class HacsFrontendDev(HomeAssistantView):
  75. """Dev View Class for HACS."""
  76. requires_auth = False
  77. name = "hacs_files:frontend"
  78. url = r"/hacsfiles/frontend/{requested_file:.+}"
  79. async def get(self, request, requested_file): # pylint: disable=unused-argument
  80. """Handle HACS Web requests."""
  81. hacs: HacsBase = request.app["hass"].data.get(DOMAIN)
  82. requested = requested_file.split("/")[-1]
  83. request = await hacs.session.get(f"{hacs.configuration.frontend_repo_url}/{requested}")
  84. if request.status == 200:
  85. result = await request.read()
  86. response = web.Response(body=result)
  87. response.headers["Content-Type"] = "application/javascript"
  88. return response