diff --git a/custom_components/material_symbols/__init__.py b/custom_components/material_symbols/__init__.py index a5d857da..276e80a2 100644 --- a/custom_components/material_symbols/__init__.py +++ b/custom_components/material_symbols/__init__.py @@ -18,36 +18,47 @@ ICONS_PATH = f"custom_components/{DOMAIN}/data" LOADER_PATH = f"custom_components/{DOMAIN}/material_symbols.js" -class ListingView(HomeAssistantView): +class ListingView(HomeAssistantView): requires_auth = False def __init__(self, url, iconset_path, hass, iconset_prefix): self.url = url - self.name = f"api:{DOMAIN}:icons:{iconset_prefix}" + self.name = f"api:{DOMAIN}:{iconset_prefix}" self.iconset_path = iconset_path self.hass = hass + LOGGER.debug(f"ListingView initialised with URL: {self.url}, " + f"iconset_path: {self.iconset_path}, " + f"iconset_prefix: {iconset_prefix}") async def get(self, request): + # Fetch the icons list icons_list = await self.hass.async_add_executor_job( self.get_icons_list, self.iconset_path ) + LOGGER.debug(f"Icons list served: {icons_list}") return self.json(icons_list) def get_icons_list(self, iconset_path): icons = [] for dirpath, dirnames, filenames in walk(iconset_path): - relative_dir = path.relpath(dirpath, iconset_path) + LOGGER.debug(f"Walking directory: {dirpath}") for fn in filenames: if fn.endswith(".svg"): - icon_name = path.join(relative_dir, fn[:-4]).replace(path.sep, '/') + # Remove potential './' or subdirectory paths + icon_name = fn[:-4] + LOGGER.debug(f"Found icon: {icon_name}") icons.append({"name": icon_name}) + LOGGER.debug(f"Final icons list: {icons}") return icons + async def async_setup(hass: HomeAssistant, config): + LOGGER.debug(f"Setting up Material Symbols with version {VERSION}") await hass.http.async_register_static_paths( [StaticPathConfig(LOADER_URL, hass.config.path(LOADER_PATH), True)] ) + LOGGER.debug(f"Static JS path registered: {LOADER_URL}") add_extra_js_url(hass, LOADER_URL) iconset_prefixes = ["m3o", "m3of", "m3r", "m3rf", "m3s", "m3sf"] @@ -56,20 +67,28 @@ async def async_setup(hass: HomeAssistant, config): icons_path = hass.config.path(f"{ICONS_PATH}/{iconset_prefix}") icons_list_url = f"{icons_url}/icons.json" + LOGGER.debug(f"Registering static path: {icons_url} -> {icons_path}") await hass.http.async_register_static_paths( [StaticPathConfig(icons_url, icons_path, True)] ) + LOGGER.debug(f"Registering API view: {icons_list_url}") hass.http.register_view( ListingView(icons_list_url, icons_path, hass, iconset_prefix) ) + LOGGER.info("Material Symbols setup complete.") return True + async def async_setup_entry(hass, entry): + LOGGER.info(f"Setting up entry for Material Symbols: {entry}") return True + async def async_remove_entry(hass, entry): + LOGGER.info(f"Removing entry for Material Symbols: {entry}") return True + async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Migrate from old entry.""" if entry.version == 1: diff --git a/custom_components/material_symbols/material_symbols.js b/custom_components/material_symbols/material_symbols.js index 56618bba..c245dc57 100644 --- a/custom_components/material_symbols/material_symbols.js +++ b/custom_components/material_symbols/material_symbols.js @@ -1 +1 @@ -(()=>{"use strict";const o="material_symbols",r={},t={},n=async t=>{if(r[t])return r[t];const n=`/${o}/${t}/icons.json`;try{const o=await fetch(n);if(!o.ok)throw new Error(`Failed to fetch icons.json for ${t}`);const s=await o.json();return r[t]=s.map((o=>o.name)),r[t]}catch(o){return console.error(`Error loading icons.json for ${t}:`,o),[]}},s=["m3o","m3of","m3s","m3sf","m3r","m3rf"];(async()=>{await(async o=>{const r=o.map((async o=>{try{await n(o)}catch(r){console.error(`Failed to preload icons.json for prefix: ${o}`,r)}}));await Promise.all(r)})(s),s.forEach((r=>{window.customIcons[r]={getIcon:n=>(async(r,n)=>{const s=`${r}:${n}`;if(t[s])return t[s];const a=`/${o}/${r}/${n}.svg`;try{const o=await fetch(a);if(!o.ok)throw new Error(`Failed to fetch icon ${n} from ${r}`);const e=await o.text(),i=(new DOMParser).parseFromString(e,"image/svg+xml").querySelector("svg");if(!i)return null;const c={viewBox:i.getAttribute("viewBox")||"0 0 24 24",path:Array.from(i.querySelectorAll("path")).map((o=>o.getAttribute("d"))).join(" ")};return t[s]=c,c}catch(o){return console.error(`Error fetching icon ${n} from ${r}:`,o),null}})(r,n),getIconList:()=>(async o=>(await n(o)).map((o=>({name:o}))))(r)}}))})(),console.info("%c MATERIAL SYMBOLS %c %c 2024.11.23 ",'@import url("https://fonts.googleapis.com/css2?family=Roboto");background-color:#1FBEF2;color:#FFFFFF;padding:3px 43px 2px 8px;border-radius:999vh;border:5px solid #1FBEF2;font-family:"Roboto", sans-serif;margin-top:18px','@import url("https://fonts.googleapis.com/css2?family=Roboto");background-color:#FFFFFF;color:#1FBEF2;padding:3px 8px 2px 0;border-radius:999vh 0 0 999vh;border:0;font-family:"Roboto", sans-serif;margin-left:-94px','@import url("https://fonts.googleapis.com/css2?family=Roboto");background-color:#FFFFFF;color:#1FBEF2;padding:3px 9px 2px 0;border-radius:0 999vh 999vh 0;border:0;font-family:"Roboto", sans-serif;margin-left:-1px;margin-bottom:18px')})(); \ No newline at end of file +(()=>{"use strict";let o="material_symbols",t={},r={},a=async r=>{if(t[r])return t[r];let a=`/${o}/${r}/icons.json`;try{let e=await fetch(a);if(!e.ok)throw Error(`Failed to fetch icons.json for ${r}`);let i=await e.json();return t[r]=i.map(o=>o.name),t[r]}catch(s){return[]}},e=["m3o","m3of","m3s","m3sf","m3r","m3rf"];(async()=>{await (async o=>{let t=o.map(async o=>{try{await a(o)}catch(t){}});await Promise.all(t)})(e),e.forEach(t=>{window.customIcons[t]={getIcon:a=>(async(t,a)=>{let e=`${t}:${a}`;if(r[e])return r[e];let i=`/${o}/${t}/${a}.svg`;try{let s=await fetch(i);if(!s.ok)throw Error(`Failed to fetch icon ${a} from ${t}`);let n=await s.text(),l=new DOMParser().parseFromString(n,"image/svg+xml").querySelector("svg");if(!l)return null;let c={viewBox:l.getAttribute("viewBox")||"0 0 24 24",path:Array.from(l.querySelectorAll("path")).map(o=>o.getAttribute("d")).join(" ")};return r[e]=c,c}catch(m){return null}})(t,a),getIconList:()=>(async o=>(await a(o)).map(o=>({name:o})))(t)}})})(),console.info("%c MATERIAL SYMBOLS %c %c 2024.11.23 ",'@import url("https://fonts.googleapis.com/css2?family=Roboto");background-color:#1FBEF2;color:#FFFFFF;padding:3px 43px 2px 8px;border-radius:999vh;border:5px solid #1FBEF2;font-family:"Roboto", sans-serif;margin-top:18px','@import url("https://fonts.googleapis.com/css2?family=Roboto");background-color:#FFFFFF;color:#1FBEF2;padding:3px 8px 2px 0;border-radius:999vh 0 0 999vh;border:0;font-family:"Roboto", sans-serif;margin-left:-94px','@import url("https://fonts.googleapis.com/css2?family=Roboto");background-color:#FFFFFF;color:#1FBEF2;padding:3px 9px 2px 0;border-radius:0 999vh 999vh 0;border:0;font-family:"Roboto", sans-serif;margin-left:-1px;margin-bottom:18px')})(); \ No newline at end of file