import { t } from "../../services/i18n.js";
import BasicWidget from "../basic_widget.js";
import utils from "../../services/utils.js";
import UpdateAvailableWidget from "./update_available.js";
import options from "../../services/options.js";
const TPL = `
${t('global_menu.open_new_window')}
${t('global_menu.show_shared_notes_subtree')}
${t('global_menu.zoom')}
${t('title_bar_buttons.window-on-top')}
${t('global_menu.switch_to_mobile_version')}
${t('global_menu.switch_to_desktop_version')}
${t('global_menu.configure_launchbar')}
${t('global_menu.advanced')}
${t('global_menu.show_hidden_subtree')}
${t('global_menu.open_search_history')}
${t('global_menu.show_backend_log')}
${t('global_menu.open_sql_console')}
${t('global_menu.open_sql_console_history')}
${t('global_menu.open_dev_tools')}
${t('global_menu.reload_frontend')}
${t('global_menu.options')}
${t('global_menu.show_help')}
${t('global_menu.about')}
${t('global_menu.logout')}
`;
export default class GlobalMenuWidget extends BasicWidget {
private updateAvailableWidget: UpdateAvailableWidget;
private isHorizontalLayout: boolean;
private tooltip!: bootstrap.Tooltip;
private dropdown!: bootstrap.Dropdown;
private $updateToLatestVersionButton!: JQuery;
private $zoomState!: JQuery;
constructor(isHorizontalLayout: boolean) {
super();
this.updateAvailableWidget = new UpdateAvailableWidget();
this.isHorizontalLayout = isHorizontalLayout;
}
doRender() {
this.$widget = $(TPL);
if (!this.isHorizontalLayout) {
this.$widget.addClass("dropend");
}
const $globalMenuButton = this.$widget.find(".global-menu-button")
if (!this.isHorizontalLayout) {
$globalMenuButton.prepend($(`\
`));
//TODO: Fix once bootstrap is imported via modules.
//@ts-ignore
this.tooltip = new bootstrap.Tooltip(this.$widget.find("[data-bs-toggle='tooltip']"), { trigger: "hover" });
} else {
$globalMenuButton.toggleClass("bx bx-menu");
}
//TODO: Fix once bootstrap is imported via modules.
//@ts-ignore
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"), {
alignment: "bottom"
});
this.$widget.find(".show-about-dialog-button").on('click', () => this.triggerCommand("openAboutDialog"));
const isElectron = utils.isElectron();
this.$widget.find(".toggle-pin").toggle(isElectron);
if (isElectron) {
this.$widget.on("click", ".toggle-pin", (e) => {
const $el = $(e.target);
const remote = utils.dynamicRequire('@electron/remote');
const focusedWindow = remote.BrowserWindow.getFocusedWindow();
const isAlwaysOnTop = focusedWindow.isAlwaysOnTop()
if (isAlwaysOnTop) {
focusedWindow.setAlwaysOnTop(false)
$el.removeClass('active');
} else {
focusedWindow.setAlwaysOnTop(true);
$el.addClass('active');
}
});
}
this.$widget.find(".logout-button").toggle(!isElectron);
this.$widget.find(".logout-button-separator").toggle(!isElectron);
this.$widget.find(".open-dev-tools-button").toggle(isElectron);
this.$widget.find(".switch-to-mobile-version-button").toggle(!isElectron && utils.isDesktop());
this.$widget.find(".switch-to-desktop-version-button").toggle(!isElectron && utils.isMobile());
this.$widget.on('click', '.dropdown-item', e => {
if ($(e.target).parent(".zoom-buttons")) {
return;
}
this.dropdown.toggle();
});
this.$widget.on('click', '.dropdown-submenu', e => {
if ($(e.target).children(".dropdown-menu").length === 1 || $(e.target).hasClass('dropdown-toggle')) {
e.stopPropagation();
}
})
this.$widget.find(".global-menu-button-update-available").append(
this.updateAvailableWidget.render()
);
this.$updateToLatestVersionButton = this.$widget.find(".update-to-latest-version-button");
if (!utils.isElectron()) {
this.$widget.find(".zoom-container").hide();
this.$widget.find(".zoom-container-separator").hide();
}
this.$zoomState = this.$widget.find(".zoom-state");
this.$widget.on('show.bs.dropdown', () => {
this.updateZoomState();
if (this.tooltip) {
this.tooltip.hide();
this.tooltip.disable();
}
});
if (this.tooltip) {
this.$widget.on('hide.bs.dropdown', () => this.tooltip.enable());
}
this.$widget.find(".zoom-buttons").on("click",
// delay to wait for the actual zoom change
() => setTimeout(() => this.updateZoomState(), 300)
);
this.updateVersionStatus();
setInterval(() => this.updateVersionStatus(), 8 * 60 * 60 * 1000);
}
updateZoomState() {
if (!utils.isElectron()) {
return;
}
const zoomFactor = utils.dynamicRequire('electron').webFrame.getZoomFactor();
const zoomPercent = Math.round(zoomFactor * 100);
this.$zoomState.text(`${zoomPercent}%`);
}
async updateVersionStatus() {
await options.initializedPromise;
if (options.get("checkForUpdates") !== 'true') {
return;
}
const latestVersion = await this.fetchLatestVersion();
this.updateAvailableWidget.updateVersionStatus(latestVersion);
// Show "click to download" button in options menu if there's a new version available
this.$updateToLatestVersionButton.toggle(utils.isUpdateAvailable(latestVersion, glob.triliumVersion));
this.$updateToLatestVersionButton.find(".version-text").text(`Version ${latestVersion} is available, click to download.`);
}
async fetchLatestVersion() {
const RELEASES_API_URL = "https://api.github.com/repos/TriliumNext/Notes/releases/latest";
const resp = await fetch(RELEASES_API_URL);
const data = await resp.json();
return data?.tag_name?.substring(1);
}
downloadLatestVersionCommand() {
window.open("https://github.com/TriliumNext/Notes/releases/latest");
}
activeContextChangedEvent() {
this.dropdown.hide();
}
noteSwitchedEvent() {
this.dropdown.hide();
}
}