zulip/static/js/favicon.js

64 lines
2.2 KiB
JavaScript
Raw Normal View History

import $ from "jquery";
import render_favicon_svg from "../templates/favicon.svg.hbs";
import * as blueslip from "./blueslip";
import favicon_font_url from "!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);
}
}