import $ from "jquery"; import render_feedback_container from "../templates/feedback_container.hbs"; import * as blueslip from "./blueslip"; /* This code lets you show something like this: +----- | TOPIC MUTES [undo] [x] | | You muted stream Foo, topic Bar. +----- And then you configure the undo behavior, and everything else is controlled by the widget. Code-wise it's a singleton widget that controls the DOM inside #feedback_container, which gets served up by server. */ const meta = { hide_me_time: null, alert_hover_state: false, $container: null, opened: false, }; const animate = { maybe_close() { if (!meta.opened) { return; } if (meta.hide_me_time < Date.now() && !meta.alert_hover_state) { animate.fadeOut(); return; } setTimeout(animate.maybe_close, 100); }, fadeOut() { if (!meta.opened) { return; } if (meta.$container) { meta.$container.fadeOut(500).removeClass("show"); meta.opened = false; meta.alert_hover_state = false; } }, fadeIn() { if (meta.opened) { return; } if (meta.$container) { meta.$container.fadeIn(500).addClass("show"); meta.opened = true; setTimeout(animate.maybe_close, 100); } }, }; function set_up_handlers() { if (meta.handlers_set) { return; } meta.handlers_set = true; // if the user mouses over the notification, don't hide it. meta.$container.on("mouseenter", () => { if (!meta.opened) { return; } meta.alert_hover_state = true; }); // once the user's mouse leaves the notification, restart the countdown. meta.$container.on("mouseleave", () => { if (!meta.opened) { return; } meta.alert_hover_state = false; // add at least 2000ms but if more than that exists just keep the // current amount. meta.hide_me_time = Math.max(meta.hide_me_time, Date.now() + 2000); }); meta.$container.on("click", ".exit-me", () => { animate.fadeOut(); }); meta.$container.on("click", ".feedback_undo", () => { if (meta.undo) { meta.undo(); } animate.fadeOut(); }); } export function is_open() { return meta.opened; } export function dismiss() { animate.fadeOut(); } export function show(opts) { if (!opts.populate) { blueslip.error("programmer needs to supply populate callback."); return; } meta.$container = $("#feedback_container"); const html = render_feedback_container(); meta.$container.html(html); set_up_handlers(); meta.undo = opts.on_undo; // add a four second delay before closing up. meta.hide_me_time = Date.now() + 4000; meta.$container.find(".feedback_title").text(opts.title_text); meta.$container.find(".feedback_undo").text(opts.undo_button_text); opts.populate(meta.$container.find(".feedback_content")); animate.fadeIn(); }