import { LitElement, css, html } from "lit"; import { resolveMarkdown } from "lit-markdown"; import { customElement, property, query } from "lit/decorators.js"; import changelog from "../../resources/changelog.md"; import megaphone from "../../resources/images/Megaphone.svg"; import version from "../../resources/version.txt"; import { translateText } from "../client/Utils"; import "./components/baseComponents/Button"; import "./components/baseComponents/Modal"; @customElement("news-modal") export class NewsModal extends LitElement { @query("o-modal") private modalEl!: HTMLElement & { open: () => void; close: () => void; }; connectedCallback() { super.connectedCallback(); window.addEventListener("keydown", this.handleKeyDown); } disconnectedCallback() { window.removeEventListener("keydown", this.handleKeyDown); super.disconnectedCallback(); } private handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); } }; @property({ type: String }) markdown = "Loading..."; private initialized: boolean = false; static styles = css` :host { display: block; } .news-container { overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: 1.5rem; } .news-content { color: #ddd; line-height: 1.5; background: rgba(0, 0, 0, 0.6); border-radius: 8px; padding: 1rem; } .news-content a { color: #4a9eff !important; text-decoration: underline !important; transition: color 0.2s ease; } .news-content a:hover { color: #6fb3ff !important; } `; render() { return html`
${resolveMarkdown(this.markdown, { includeImages: true, includeCodeBlockClassNames: true, })}
${translateText("news.see_all_releases")} ${translateText("news.github_link")}.
`; } public open() { if (!this.initialized) { this.initialized = true; fetch(changelog) .then((response) => (response.ok ? response.text() : "Failed to load")) .then((markdown) => markdown .replace( /(? `[#${prNumber}](https://github.com/openfrontio/OpenFrontIO/pull/${prNumber})`, ) .replace( /(? `[${comparison}](https://github.com/openfrontio/OpenFrontIO/compare/${comparison})`, ), ) .then((markdown) => (this.markdown = markdown)); } this.requestUpdate(); this.modalEl?.open(); } private close() { this.modalEl?.close(); } } @customElement("news-button") export class NewsButton extends LitElement { @query("news-modal") private newsModal!: NewsModal; connectedCallback() { super.connectedCallback(); this.checkForNewVersion(); } private checkForNewVersion() { const lastSeenVersion = localStorage.getItem("last-seen-version"); if (lastSeenVersion !== null && lastSeenVersion !== version) { setTimeout(() => { this.openNewsModel(); }, 500); } } private openNewsModel() { localStorage.setItem("last-seen-version", version); this.newsModal.open(); } render() { return html`
`; } createRenderRoot() { return this; } }