import $ from "jquery"; import render_favicon_svg from "../templates/favicon.svg.hbs"; import * as blueslip from "./blueslip"; import favicon_font_url from "./favicon_font_url!=!url-loader!font-subset-loader2?glyphs=0123456789KMGT∞!source-sans/TTF/SourceSans3-Bold.ttf"; let favicon_state; function set_favicon() { $("#favicon").attr("href", favicon_state.url); } export function update_favicon(new_message_count, pm_count) { try { if (favicon_state !== undefined) { favicon_state.image.removeEventListener("load", set_favicon); // We need to remove this src so revokeObjectURL doesn't cause a // net::ERR_FILE_NOT_FOUND error in Chrome. This seems to be the // simplest way to do that without triggering an expensive network // request or spewing a different console error. favicon_state.image.src = "data:,"; URL.revokeObjectURL(favicon_state.url); favicon_state = undefined; } if (new_message_count === 0 && pm_count === 0) { $("#favicon").attr("href", "/static/images/favicon.svg?v=4"); return; } const pow = Math.floor(Math.log10(new_message_count) / 3); const suffix = ["", "K", "M", "G", "T"][pow]; const count = new_message_count === 0 ? "" : pow < 5 ? `${Math.floor(new_message_count / 1e3 ** pow)}${suffix}` : "∞"; const count_long = count.length > 2; const rendered_favicon = render_favicon_svg({ count, count_long, have_pm: pm_count !== 0, favicon_font_url, }); favicon_state = { url: URL.createObjectURL(new Blob([rendered_favicon], {type: "image/svg+xml"})), image: new Image(), }; // Without loading the SVG in an Image first, Chrome mysteriously fails to // render the webfont (https://crbug.com/1140920). favicon_state.image.src = favicon_state.url; favicon_state.image.addEventListener("load", set_favicon); } catch (error) { blueslip.error("Failed to update favicon", undefined, error.stack); } }