diff --git a/apps/client/src/widgets/buttons/global_menu.css b/apps/client/src/widgets/buttons/global_menu.css index 23bf1eae8..920308dea 100644 --- a/apps/client/src/widgets/buttons/global_menu.css +++ b/apps/client/src/widgets/buttons/global_menu.css @@ -78,4 +78,25 @@ top: 3px; font-size: 120%; margin-right: 6px; -} \ No newline at end of file +} + +/* #region Update available */ +.global-menu-button-update-available-button { + width: 21px !important; + height: 21px !important; + padding: 0 !important; + + border-radius: var(--button-border-radius); + transform: scale(0.9); + border: none; + opacity: 0.8; + + display: flex; + align-items: center; + justify-content: center; +} + +.global-menu-button-wrapper:hover .global-menu-button-update-available-button { + opacity: 1; +} +/* #endregion */ \ No newline at end of file diff --git a/apps/client/src/widgets/buttons/global_menu.tsx b/apps/client/src/widgets/buttons/global_menu.tsx index 40bea197c..09747d9f7 100644 --- a/apps/client/src/widgets/buttons/global_menu.tsx +++ b/apps/client/src/widgets/buttons/global_menu.tsx @@ -1,6 +1,6 @@ import Dropdown from "../react/Dropdown"; import "./global_menu.css"; -import { useStaticTooltip, useStaticTooltipWithKeyboardShortcut } from "../react/hooks"; +import { useStaticTooltip, useStaticTooltipWithKeyboardShortcut, useTriliumOption, useTriliumOptionBool } from "../react/hooks"; import { useContext, useEffect, useRef, useState } from "preact/hooks"; import { t } from "../../services/i18n"; import { FormDropdownDivider, FormDropdownSubmenu, FormListItem } from "../react/FormList"; @@ -10,7 +10,7 @@ import { KeyboardActionNames } from "@triliumnext/commons"; import { ComponentChildren } from "preact"; import Component from "../../components/component"; import { ParentComponent } from "../react/react_utils"; -import { dynamicRequire, isElectron, isMobile } from "../../services/utils"; +import utils, { dynamicRequire, isElectron, isMobile } from "../../services/utils"; interface MenuItemProps { icon: string, @@ -25,12 +25,18 @@ interface MenuItemProps { export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout: boolean }) { const isVerticalLayout = !isHorizontalLayout; const parentComponent = useContext(ParentComponent); + const { isUpdateAvailable, latestVersion } = useTriliumUpdateStatus(); return ( } + text={<> + {isVerticalLayout && } + {isUpdateAvailable && } + } forceShown > @@ -56,6 +62,7 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout: + {isUpdateAvailable && window.open("https://github.com/TriliumNext/Trilium/releases/latest")} icon="bx bx-sync" text={`Version ${latestVersion} is available, click to download.`} /> } @@ -190,4 +197,33 @@ function ToggleWindowOnTop() { }} /> ) +} + +function useTriliumUpdateStatus() { + const [ latestVersion, setLatestVersion ] = useState(); + const [ checkForUpdates ] = useTriliumOptionBool("checkForUpdates"); + const isUpdateAvailable = utils.isUpdateAvailable(latestVersion, glob.triliumVersion); + + async function updateVersionStatus() { + const RELEASES_API_URL = "https://api.github.com/repos/TriliumNext/Trilium/releases/latest"; + + const resp = await fetch(RELEASES_API_URL); + const data = await resp.json(); + const latestVersion = data?.tag_name?.substring(1); + setLatestVersion(latestVersion); + } + + useEffect(() => { + if (!checkForUpdates) { + setLatestVersion(undefined); + return; + } + + updateVersionStatus(); + + const interval = setInterval(() => updateVersionStatus(), 8 * 60 * 60 * 1000); + return () => clearInterval(interval); + }, [ checkForUpdates ]); + + return { isUpdateAvailable, latestVersion }; } \ No newline at end of file diff --git a/apps/client/src/widgets/buttons/update_available.ts b/apps/client/src/widgets/buttons/update_available.ts deleted file mode 100644 index 2f2535cc0..000000000 --- a/apps/client/src/widgets/buttons/update_available.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { t } from "../../services/i18n.js"; -import BasicWidget from "../basic_widget.js"; -import utils from "../../services/utils.js"; - -const TPL = /*html*/` -
- - - -
-`; - -export default class UpdateAvailableWidget extends BasicWidget { - doRender() { - this.$widget = $(TPL); - } - - updateVersionStatus(latestVersion: string) { - this.$widget.toggle(utils.isUpdateAvailable(latestVersion, glob.triliumVersion)); - } -}