diff --git a/src/css/injected.scss b/src/css/injected.scss index 90023d81..162e113a 100644 --- a/src/css/injected.scss +++ b/src/css/injected.scss @@ -158,6 +158,16 @@ select { color: var(--text-primary); position: relative; } +#main { + > .timetablepage { + > .quickbar { + .gutter { + border-bottom-left-radius: 15px; + border-bottom-right-radius: 15px; + } + } + } +} .forums { color: var(--text-color); } @@ -823,11 +833,18 @@ div > ol:has(.uiFileHandlerWrapper) { box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.2); } -html.transparencyEffects [class*="ResourceList__ResourceItem___voTSd"], -html.transparencyEffects [class*="ResourceList__ResourceItem___voTSd"] [class*="ResourceList__name___ydvDT"] { +html.transparencyEffects [class*="BasicPanel__BasicPanel___q92_U"] > ol > li { border-bottom: none !important; } +html.transparencyEffects + [class*="BasicPanel__BasicPanel___q92_U"] + > ol + > li + + li { + border-top: 1px solid var(--theme-offset-bg); +} + .assessmentsWrapper .message { display: none; } @@ -983,7 +1000,7 @@ html.transparencyEffects [class*="ResourceList__ResourceItem___voTSd"] [class*=" top: 72px; left: 0px; z-index: 10; - + @media (min-width: 1401px) { position: absolute; left: 402px; @@ -1690,7 +1707,7 @@ iframe.userHTML { } .programmeNavigator { - box-shadow: 0 0 40px 0px rgba(0,0,0,0.05); + box-shadow: 0 0 40px 0px rgba(0, 0, 0, 0.05); overflow-y: scroll; height: 100%; @@ -1749,7 +1766,7 @@ iframe.userHTML { &.selected { background: transparent !important; } - + &::before { content: ""; position: absolute; @@ -1761,7 +1778,9 @@ iframe.userHTML { background: var(--auto-background); opacity: 0; scale: 0.95; - transition: opacity 0.2s ease-out, scale 0.1s ease-out; + transition: + opacity 0.2s ease-out, + scale 0.1s ease-out; z-index: -1; pointer-events: none; } @@ -1775,13 +1794,12 @@ iframe.userHTML { opacity: 1; scale: 1; } - } } } .pane { - .content:has(.programmeNavigator) { + .content:has(.programmeNavigator) { margin: 0; } @@ -1799,7 +1817,9 @@ iframe.userHTML { .dark .programmeNavigator .navigator { .search { background: var(--background-secondary) !important; - box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1), inset 0px 0px 15px 0px rgba(0, 0, 0, 0.1) !important; + box-shadow: + 0px 0px 10px 0px rgba(0, 0, 0, 0.1), + inset 0px 0px 15px 0px rgba(0, 0, 0, 0.1) !important; } } .dark #main > .course > .content > h1 { @@ -2028,7 +2048,7 @@ div.entry.new { div.liveEntry { border-radius: 4px; -} +} div.dailycalMarker { border-radius: 4px; @@ -2179,24 +2199,23 @@ div.bar.flat { background: var(--background-secondary) !important; } -.dashlet-motd { - padding: 7px !important; - .message { - font-size: 24px !important; - border-radius: 12px !important; - border: none !important; - box-shadow: none !important; - color: #fff !important; - padding: 16px !important; - margin: 0 !important; - height: 100% !important; - max-height: none !important; - display: flex !important; - align-items: flex-start !important; - overflow: hidden !important; + .dashlet-motd { + padding: 7px !important; + .message { + font-size: 24px !important; + border-radius: 12px !important; + border: none !important; + box-shadow: none !important; + color: #fff !important; + padding: 16px !important; + margin: 0 !important; + height: 100% !important; + max-height: none !important; + display: flex !important; + align-items: flex-start !important; + overflow: hidden !important; + } } -} - .cke_toolbox > .cke_toolbar > .cke_toolgroup > .cke_button { background: var(--background-secondary) !important; @@ -3750,14 +3769,19 @@ div.day-empty { } .notice-unified-content { - h1, h2, h3, h4, h5, h6 { + h1, + h2, + h3, + h4, + h5, + h6 { margin: 0 !important; padding: 0 !important; font-weight: inherit !important; color: inherit !important; text-shadow: none !important; } - + .notice-header { display: flex; justify-content: space-between; @@ -3766,7 +3790,7 @@ div.day-empty { margin-bottom: 12px; gap: 16px; } - + .notice-content-title { font-size: 20px !important; // Nice middle ground - not too big, not too small font-weight: 600 !important; @@ -3775,7 +3799,7 @@ div.day-empty { line-height: 1.3 !important; flex-shrink: 0; } - + .notice-content-body { font-size: 14px !important; color: var(--text-secondary) !important; @@ -3787,72 +3811,73 @@ div.day-empty { min-width: 600px; // Ensure tables have consistent width for layout width: 100%; } - + // The ONLY difference between states is clipping! - &.notice-card-state { + &.notice-card-state { .notice-content-body { // Clip to show only 2 lines but keep full layout overflow: hidden; max-height: 3em; // ~2 lines worth of height } } - + &.notice-modal-state { .notice-close-btn { opacity: 1; } - + .notice-content-body { // Show full content with scrolling overflow-y: auto; - + // Custom scrollbar for long content &::-webkit-scrollbar { width: 6px; } - + &::-webkit-scrollbar-track { background: transparent; } - + &::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 3px; } - - &::-webkit-scrollbar-thumb:hover { - background: rgba(255, 255, 255, 0.3); - } - // Style content elements nicely - p { - margin-bottom: 12px; - - &:last-child { - margin-bottom: 0; - } - } + &::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.3); + } - a { - color: var(--theme-primary); - text-decoration: none; + // Style content elements nicely + p { + margin-bottom: 12px; - &:hover { - text-decoration: underline; - } - } + &:last-child { + margin-bottom: 0; + } + } - ul, ol { - margin: 12px 0; - padding-left: 20px; - } + a { + color: var(--theme-primary); + text-decoration: none; - li { - margin-bottom: 4px; - } - } - } - } + &:hover { + text-decoration: underline; + } + } + + ul, + ol { + margin: 12px 0; + padding-left: 20px; + } + + li { + margin-bottom: 4px; + } + } + } +} .notice-header { display: flex; @@ -3952,21 +3977,21 @@ button.notice-close-btn { color: var(--text-secondary); flex: 1; overflow-y: auto; - + // Custom scrollbar &::-webkit-scrollbar { width: 6px; } - + &::-webkit-scrollbar-track { background: transparent; } - + &::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 3px; } - + &::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.3); } @@ -3974,7 +3999,7 @@ button.notice-close-btn { // Style content elements p { margin-bottom: 12px; - + &:last-child { margin-bottom: 0; } @@ -3989,7 +4014,8 @@ button.notice-close-btn { } } - ul, ol { + ul, + ol { margin: 12px 0; padding-left: 20px; } @@ -4003,7 +4029,7 @@ button.notice-close-btn { .dark { .notice-card { border-color: rgba(255, 255, 255, 0.05); - + &:hover { border-color: rgba(255, 255, 255, 0.1); } @@ -4036,7 +4062,7 @@ button.notice-close-btn { .notice-card { padding: 12px; } - + .notice-preview { font-size: 13px; } diff --git a/src/interface/pages/settings.svelte b/src/interface/pages/settings.svelte index 5be5f0d2..e97079f8 100644 --- a/src/interface/pages/settings.svelte +++ b/src/interface/pages/settings.svelte @@ -11,8 +11,8 @@ import { closeExtensionPopup } from "@/seqta/utils/Closers/closeExtensionPopup"; import { OpenAboutPage } from "@/seqta/utils/Openers/OpenAboutPage"; - import { OpenWhatsNewPopup } from "@/seqta/utils/Whatsnew"; - import { OpenMinecraftServerPopup } from "@/seqta/utils/AboutMinecraftServer"; + import { OpenWhatsNewPopup } from "@/seqta/utils/Openers/OpenWhatsNewPopup"; + import { OpenMinecraftServerPopup } from "@/seqta/utils/Openers/OpenMinecraftServerPopup"; import ColourPicker from "../components/ColourPicker.svelte"; import { settingsPopup } from "../hooks/SettingsPopup"; @@ -103,7 +103,7 @@ {#if !standalone} diff --git a/src/plugins/built-in/notificationCollector/index.ts b/src/plugins/built-in/notificationCollector/index.ts index 9763f4dd..dc4576c1 100644 --- a/src/plugins/built-in/notificationCollector/index.ts +++ b/src/plugins/built-in/notificationCollector/index.ts @@ -39,7 +39,7 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = { "[class*='notifications__bubble___']", ) as HTMLElement; - if (api.storage.lastNotificationCount !== 0) { + if (alertDiv && api.storage.lastNotificationCount !== 0) { alertDiv.textContent = api.storage.lastNotificationCount.toString(); } @@ -63,7 +63,7 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = { const notificationCount = data.payload.notifications.length; api.storage.lastNotificationCount = notificationCount; api.storage.lastCheckedTime = new Date().toISOString(); - + // Reset error count on success api.storage.consecutiveErrors = 0; @@ -74,31 +74,36 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = { } } catch (error) { console.error("[BetterSEQTA+] Error fetching notifications:", error); - api.storage.consecutiveErrors = (api.storage.consecutiveErrors || 0) + 1; + api.storage.consecutiveErrors = + (api.storage.consecutiveErrors || 0) + 1; } }; const getNextInterval = () => { // Exponential backoff on errors, max 5 minutes - const errorMultiplier = Math.min(Math.pow(2, api.storage.consecutiveErrors || 0), 10); + const errorMultiplier = Math.min( + Math.pow(2, api.storage.consecutiveErrors || 0), + 10, + ); return Math.min(baseInterval * errorMultiplier, maxInterval); }; const startPolling = () => { if (pollInterval) return; // Already polling checkNotifications(); - + const scheduleNext = () => { const interval = getNextInterval(); pollInterval = window.setTimeout(() => { checkNotifications().then(() => { - if (pollInterval) { // Only continue if not stopped + if (pollInterval) { + // Only continue if not stopped scheduleNext(); } }); }, interval); }; - + scheduleNext(); }; @@ -124,14 +129,16 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = { isVisible = !document.hidden; if (isVisible && !pollInterval) { // Resume polling when tab becomes visible - const alertDiv = document.querySelector("[class*='notifications__bubble___']"); + const alertDiv = document.querySelector( + "[class*='notifications__bubble___']", + ); if (alertDiv) { startPolling(); } } }; - document.addEventListener('visibilitychange', handleVisibilityChange); + document.addEventListener("visibilitychange", handleVisibilityChange); api.seqta.onMount("[class*='notifications__bubble___']", (_) => { startPolling(); @@ -139,7 +146,7 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = { return () => { stopPolling(); - document.removeEventListener('visibilitychange', handleVisibilityChange); + document.removeEventListener("visibilitychange", handleVisibilityChange); }; }, }; diff --git a/src/plugins/monofile.ts b/src/plugins/monofile.ts index 4a692dad..ecd5f780 100644 --- a/src/plugins/monofile.ts +++ b/src/plugins/monofile.ts @@ -23,12 +23,9 @@ import { updateAllColors } from "@/seqta/ui/colors/Manager"; import loading from "@/seqta/ui/Loading"; import { SendNewsPage } from "@/seqta/utils/SendNewsPage"; import { loadHomePage } from "@/seqta/utils/Loaders/LoadHomePage"; -import { OpenWhatsNewPopup } from "@/seqta/utils/Whatsnew"; -//import { OpenMinecraftServerPopup } from "@/seqta/utils/AboutMinecraftServer"; +import { OpenWhatsNewPopup } from "@/seqta/utils/Openers/OpenWhatsNewPopup"; -import { - updateTimetableTimes, -} from "@/seqta/utils/updateTimetableTimes"; +import { updateTimetableTimes } from "@/seqta/utils/updateTimetableTimes"; // JSON content import MenuitemSVGKey from "@/seqta/content/MenuItemSVGKey.json"; diff --git a/src/seqta/utils/Openers/OpenAboutPage.ts b/src/seqta/utils/Openers/OpenAboutPage.ts index f06b6785..450daf44 100644 --- a/src/seqta/utils/Openers/OpenAboutPage.ts +++ b/src/seqta/utils/Openers/OpenAboutPage.ts @@ -1,25 +1,17 @@ import stringToHTML from "../stringToHTML"; import { settingsState } from "../listeners/SettingsState"; -import { animate, stagger } from "motion"; -import { DeleteWhatsNew } from "../Whatsnew"; +import { openPopup } from "./PopupManager"; export function OpenAboutPage() { - const background = document.createElement("div"); - background.id = "whatsnewbk"; - background.classList.add("whatsnewBackground"); - - const container = document.createElement("div"); - container.classList.add("whatsnewContainer"); - - var header: any = stringToHTML( + const header = stringToHTML( /* html */ `

About

About the extension

`, - ).firstChild; + ).firstChild as HTMLElement; - let text = stringToHTML(/* html */ ` + const text = stringToHTML(/* html */ `

BetterSEQTA+ is a fork of BetterSEQTA (originally developed by Nulkem), which was discontinued. BetterSEQTA+ continued development of BetterSEQTA, while incorporating a plethora of features.

@@ -37,9 +29,9 @@ export function OpenAboutPage() { style="width: 100%; max-width: 500px; height: auto; object-fit: contain; display: block; margin: -110px auto 0;">
- `).firstChild; + `).firstChild as HTMLElement; - let footer = stringToHTML(/* html */ ` + const footer = stringToHTML(/* html */ `
Resources and Feedback: @@ -67,56 +59,10 @@ export function OpenAboutPage() {
- `).firstChild; + `).firstChild as HTMLElement; - let exitbutton = document.createElement("div"); - exitbutton.id = "whatsnewclosebutton"; - - container.append(header); - container.append(text as ChildNode); - container.append(footer as ChildNode); - container.append(exitbutton); - - background.append(container); - - document.getElementById("container")!.append(background); - - let bkelement = document.getElementById("whatsnewbk"); - let popup = document.getElementsByClassName("whatsnewContainer")[0]; - - if (settingsState.animations) { - animate( - [popup, bkelement as HTMLElement], - { scale: [0, 1] }, - { - type: "spring", - stiffness: 220, - damping: 18, - }, - ); - - animate( - ".whatsnewTextContainer *", - { opacity: [0, 1], y: [10, 0] }, - { - delay: stagger(0.05, { startDelay: 0.1 }), - duration: 0.5, - ease: [0.22, 0.03, 0.26, 1], - }, - ); - } - - delete settingsState.justupdated; - - bkelement!.addEventListener("click", function (event) { - // Check if the click event originated from the element itself and not any of its children - if (event.target === bkelement) { - DeleteWhatsNew(); - } - }); - - var closeelement = document.getElementById("whatsnewclosebutton"); - closeelement!.addEventListener("click", function () { - DeleteWhatsNew(); + openPopup({ + header, + content: [text, footer], }); } diff --git a/src/seqta/utils/AboutMinecraftServer.ts b/src/seqta/utils/Openers/OpenMinecraftServerPopup.ts similarity index 81% rename from src/seqta/utils/AboutMinecraftServer.ts rename to src/seqta/utils/Openers/OpenMinecraftServerPopup.ts index a5d16a3d..bf207a46 100644 --- a/src/seqta/utils/AboutMinecraftServer.ts +++ b/src/seqta/utils/Openers/OpenMinecraftServerPopup.ts @@ -1,24 +1,5 @@ -import { settingsState } from "./listeners/SettingsState"; -import { animate, stagger } from "motion"; -import stringToHTML from "./stringToHTML"; - -export async function DeleteWhatsNew() { - const bkelement = document.getElementById("whatsnewbk"); - const popup = document.querySelector(".whatsnewContainer") as HTMLElement; - - if (!settingsState.animations) { - bkelement?.remove(); - return; - } - - animate( - [popup, bkelement!], - { opacity: [1, 0], scale: [1, 0] }, - { ease: [0.22, 0.03, 0.26, 1] }, - ).then(() => { - bkelement?.remove(); - }); -} +import stringToHTML from "../stringToHTML"; +import { openPopup } from "./PopupManager"; export function OpenMinecraftServerPopup() { if (!document.querySelector('link[href*="minecraftia"]')) { @@ -28,45 +9,36 @@ export function OpenMinecraftServerPopup() { document.head.appendChild(fontLink); } - const background = document.createElement("div"); - background.id = "whatsnewbk"; - background.classList.add("whatsnewBackground"); - - const container = document.createElement("div"); - container.classList.add("whatsnewContainer"); - - var header: any = stringToHTML( + const header = stringToHTML( /* html */ `

Minecraft Server

The official BetterSEQTA+ Minecraft Server

`, - ).firstChild; + ).firstChild as HTMLElement; - let imagecont = document.createElement("div"); - imagecont.classList.add("whatsnewImgContainer"); + const imageContainer = document.createElement("div"); + imageContainer.classList.add("whatsnewImgContainer"); - let video = document.createElement("video"); + const video = document.createElement("video"); video.style.aspectRatio = "16/9"; video.style.background = "black"; - let source = document.createElement("source"); + const source = document.createElement("source"); source.setAttribute( "src", "https://raw.githubusercontent.com/BetterSEQTA/BetterSEQTA-Plus/main/src/resources/server-video.mp4", ); + video.autoplay = true; video.muted = true; video.loop = true; video.appendChild(source); video.classList.add("whatsnewImg"); - imagecont.appendChild(video); + imageContainer.appendChild(video); - let textcontainer = document.createElement("div"); - textcontainer.classList.add("whatsnewTextContainer"); - - let text = stringToHTML(/* html */ ` -
+ const text = stringToHTML(/* html */ ` +

Join our community in Minecraft!

Join the official BetterSEQTA+ Minecraft Server community now!

@@ -92,8 +64,7 @@ export function OpenMinecraftServerPopup() { -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, - 1px 1px 0 #000; -"> + 1px 1px 0 #000;"> mc.betterseqta.org

+ 1px 1px 0 #000;"> Version: 1.21.4

-`).firstChild; +`).firstChild as HTMLElement; - let footer = stringToHTML(/* html */ ` + const footer = stringToHTML(/* html */ `
Resources and Feedback: @@ -144,59 +114,10 @@ export function OpenMinecraftServerPopup() {
- `).firstChild; + `).firstChild as HTMLElement; - let exitbutton = document.createElement("div"); - exitbutton.id = "whatsnewclosebutton"; - - container.append( + openPopup({ header, - imagecont, - text as HTMLElement, - footer as HTMLElement, - exitbutton, - ); - - background.append(container); - - document.getElementById("container")!.append(background); - - let bkelement = document.getElementById("whatsnewbk"); - let popup = document.getElementsByClassName("whatsnewContainer")[0]; - - if (settingsState.animations) { - animate( - [popup, bkelement as HTMLElement], - { scale: [0, 1] }, - { - type: "spring", - stiffness: 220, - damping: 18, - }, - ); - - animate( - ".whatsnewTextContainer *", - { opacity: [0, 1], y: [10, 0] }, - { - delay: stagger(0.05, { startDelay: 0.1 }), - duration: 0.5, - ease: [0.22, 0.03, 0.26, 1], - }, - ); - } - - delete settingsState.justupdated; - - bkelement!.addEventListener("click", function (event) { - // Check if the click event originated from the element itself and not any of its children - if (event.target === bkelement) { - DeleteWhatsNew(); - } - }); - - var closeelement = document.getElementById("whatsnewclosebutton"); - closeelement!.addEventListener("click", function () { - DeleteWhatsNew(); + content: [imageContainer, text, footer], }); } diff --git a/src/seqta/utils/Whatsnew.ts b/src/seqta/utils/Openers/OpenWhatsNewPopup.ts similarity index 86% rename from src/seqta/utils/Whatsnew.ts rename to src/seqta/utils/Openers/OpenWhatsNewPopup.ts index 7c279a5a..6f78e73f 100644 --- a/src/seqta/utils/Whatsnew.ts +++ b/src/seqta/utils/Openers/OpenWhatsNewPopup.ts @@ -1,48 +1,22 @@ -import { settingsState } from "./listeners/SettingsState"; -import { animate, stagger } from "motion"; -import stringToHTML from "./stringToHTML"; +import stringToHTML from "../stringToHTML"; import browser from "webextension-polyfill"; import kofi from "@/resources/kofi.png?base64"; - -export async function DeleteWhatsNew() { - const bkelement = document.getElementById("whatsnewbk"); - const popup = document.getElementsByClassName("whatsnewContainer")[0]; - - if (!settingsState.animations) { - bkelement?.remove(); - return; - } - - animate( - [popup, bkelement!], - { opacity: [1, 0], scale: [1, 0] }, - { ease: [0.22, 0.03, 0.26, 1] }, - ).then(() => { - bkelement?.remove(); - }); -} +import { openPopup } from "./PopupManager"; export function OpenWhatsNewPopup() { - const background = document.createElement("div"); - background.id = "whatsnewbk"; - background.classList.add("whatsnewBackground"); - - const container = document.createElement("div"); - container.classList.add("whatsnewContainer"); - - var header: any = stringToHTML( + const header = stringToHTML( /* html */ `

What's New

BetterSEQTA+ V${browser.runtime.getManifest().version}

`, - ).firstChild; + ).firstChild as HTMLElement; - let imagecont = document.createElement("div"); - imagecont.classList.add("whatsnewImgContainer"); + const imageContainer = document.createElement("div"); + imageContainer.classList.add("whatsnewImgContainer"); - let video = document.createElement("video"); - let source = document.createElement("source"); + const video = document.createElement("video"); + const source = document.createElement("source"); source.setAttribute( "src", @@ -53,19 +27,10 @@ export function OpenWhatsNewPopup() { video.loop = true; video.appendChild(source); video.classList.add("whatsnewImg"); - imagecont.appendChild(video); + imageContainer.appendChild(video); - /* let whatsnewimg = document.createElement("img"); - //whatsnewimg.src = "https://raw.githubusercontent.com/BetterSEQTA/BetterSEQTA-Plus/main/src/resources/update-image.webp"; - whatsnewimg.src = browser.runtime.getURL('../../resources/update-image.webp'); - whatsnewimg.classList.add("whatsnewImg"); - imagecont.appendChild(whatsnewimg); */ - - let textcontainer = document.createElement("div"); - textcontainer.classList.add("whatsnewTextContainer"); - - let text = stringToHTML(/* html */ ` -
+ const text = stringToHTML(/* html */ ` +

3.4.11 - New Features & Bug Fixes

  • Added Background Music plugin
  • @@ -133,7 +98,7 @@ export function OpenWhatsNewPopup() {
  • Fixed discord icon colour in light mode
  • Fixed subject averages not showing up with letter grades
  • Tweaked compose UI
  • - +

    3.4.4 - Bug Fixes and Improvements

  • Added vertical zoom to the timetable
  • Fixed theme importing failing when images were included
  • @@ -147,15 +112,15 @@ export function OpenWhatsNewPopup() {
  • Fixed theme application in the creator
  • Performance improvements
  • Other minor bug fixes
  • - +

    3.4.3 - Minor Bug Fixes

  • Fixed a bug where timetable colours couldn't be changed
  • Other minor bug fixes
  • - +

    3.4.2 - Minor Bug Fixes

  • Fixed a bug where Assessment Average wasn't enabled by default
  • Fixed floating menus would sometimes be placed behind other elements
  • - +

    3.4.1 - Bug Fixes and Performance Improvements

  • Added a new "Subject Average" section to the assessments page
  • Fixed a bug where animations wouldn't play correctly
  • @@ -164,7 +129,7 @@ export function OpenWhatsNewPopup() {
  • Improved animation performance
  • Better Animations!
  • Minor style tweaks
  • - +

    3.4.0 - Major Performance Update

  • Completely rebuilt the extension popup using Svelte for dramatically improved performance
  • Added a brand new background store with search functionality and downloadable backgrounds
  • @@ -173,10 +138,10 @@ export function OpenWhatsNewPopup() {
  • Smoother animations and improved scrolling
  • Fixed Firefox compatibility issues
  • Other minor bug fixes and under the hood improvements
  • - +

    3.3.1 - Hot Fix

  • Fixed assessments not loading when no notices are available
  • - +

    3.3.0 - Overhauled Theming System

  • Added a theme store!
  • Added the new theme creator!
  • @@ -190,12 +155,12 @@ export function OpenWhatsNewPopup() {
  • Made animations toggle apply to settings
  • Small styling improvements
  • Other minor bug fixes
  • - - + +

    3.2.7 - Minor Improvements

  • Improved performance!
  • Fixed a bug where the icon wasn't showing up
  • - +

    3.2.6 - Bug fixes and performance improvements

  • Improved contrast for notifications
  • Added 12-hour time format toggle
  • @@ -209,7 +174,7 @@ export function OpenWhatsNewPopup() {
  • Enabled spellcheck inside of direct messages
  • Fixed timetable dates being misaligned
  • Other minor bug fixes and under the hood improvements
  • - +

    3.2.5 - More Bug Fixes

  • New direct message scroll animations
  • Added error message for brave browser shields breaking backgrounds
  • @@ -218,7 +183,7 @@ export function OpenWhatsNewPopup() {
  • Made settings panel auto size to height of screen
  • Fixed timetable dates not visible
  • Other minor bug fixes
  • - +

    3.2.4 - Bug Fixes

  • Added an open changelog button to settings
  • Fixed a memory overflow bug with Education Perfect
  • @@ -226,74 +191,74 @@ export function OpenWhatsNewPopup() {
  • Fixed news feed not loading
  • Fixed home items duplicating
  • Fixed Upcoming assessments not showing
  • - +

    3.2.2 - Minor Improvements

  • Added Settings open-close animation
  • Minor Bug Fixes
  • - +

    3.2.0 - Custom Themes

  • Added transparency (blur) effects
  • Added custom themes
  • Added colour picker history
  • Heaps of bug fixes
  • - +

    3.1.3 - Custom Backgrounds

  • Added custom backgrounds with support for images and videos
  • Overhauled topbar
  • New animated hamburger icon
  • Minor bug fixes
  • - +

    3.1.2 - New settings menu!

  • Overhauled the settings menu
  • Added custom gradients
  • Added HEAPS of animations
  • Fixed a bug where shortcuts don't show up
  • Other minor bugs fixed
  • - +

    3.1.1 - Minor Bug fixes

  • Fixed assessments overlapping
  • Fixed houses not displaying if they aren't a specific color
  • Fixed Chrome Webstore Link
  • - +

    3.1.0 - Design Improvements

  • Minor UI improvements
  • Added Animation Speed Slider
  • Animation now enables and disables without reloading SEQTA
  • Changed logo
  • - +

    3.0.0 - BetterSEQTA+ *Complete Overhaul*

  • Redesigned appearance
  • Upgraded to manifest V3 (longer support)
  • Fixed transitional glitches
  • Under the hood improvements
  • Fixed News Feed
  • - +

    2.0.7 - Added support to other domains + Minor bug fixes

  • Fixed BetterSEQTA+ not loading on some pages
  • Fixed text colour of notices being unreadable
  • Fixed pages not reloading when saving changes
  • - +

    2.0.2 - Minor bug fixes

  • Fixed indicator for current lesson
  • Fixed text colour for DM messages list in Light mode
  • Fixed user info text colour
  • - +

    Sleek New Layout

  • Updated with a new font and presentation, BetterSEQTA+ has never looked better.
  • - +

    New Updated Sidebar

  • Condensed appearance with new updated icons.
  • - +

    Independent Light Mode and Dark Mode

  • Dark mode and Light mode are now available to pick alongside your chosen Theme Colour. Your Theme Colour will now become an accent colour for the page. Light/Dark mode can be toggled with the new button, found in the top-right of the menu bar.
  • - +

    Create Custom Shortcuts

  • Found in the BetterSEQTA+ Settings menu, custom shortcuts can now be created with a name and URL of your choice.
  • - `).firstChild; + `).firstChild as HTMLElement; - let footer = stringToHTML(/* html */ ` + const footer = stringToHTML(/* html */ `
    Resources and Feedback: @@ -321,63 +286,15 @@ export function OpenWhatsNewPopup() {
    - + Buy Me a Coffee at ko-fi.com
    - `).firstChild; + `).firstChild as HTMLElement; - let exitbutton = document.createElement("div"); - exitbutton.id = "whatsnewclosebutton"; - - container.append(header); - container.append(imagecont); - container.append(textcontainer); - container.append(text as ChildNode); - container.append(footer as ChildNode); - container.append(exitbutton); - - background.append(container); - - document.getElementById("container")!.append(background); - - let bkelement = document.getElementById("whatsnewbk"); - let popup = document.getElementsByClassName("whatsnewContainer")[0]; - - if (settingsState.animations) { - animate( - [popup, bkelement as HTMLElement], - { scale: [0, 1] }, - { - type: "spring", - stiffness: 220, - damping: 18, - }, - ); - - animate( - ".whatsnewTextContainer *", - { opacity: [0, 1], y: [10, 0] }, - { - delay: stagger(0.05, { startDelay: 0.1 }), - duration: 0.5, - ease: [0.22, 0.03, 0.26, 1], - }, - ); - } - - delete settingsState.justupdated; - - bkelement!.addEventListener("click", function (event) { - // Check if the click event originated from the element itself and not any of its children - if (event.target === bkelement) { - DeleteWhatsNew(); - } - }); - - var closeelement = document.getElementById("whatsnewclosebutton"); - closeelement!.addEventListener("click", function () { - DeleteWhatsNew(); + openPopup({ + header, + content: [imageContainer, text, footer], }); } diff --git a/src/seqta/utils/Openers/PopupManager.ts b/src/seqta/utils/Openers/PopupManager.ts new file mode 100644 index 00000000..57125289 --- /dev/null +++ b/src/seqta/utils/Openers/PopupManager.ts @@ -0,0 +1,98 @@ +import { settingsState } from "../listeners/SettingsState"; +import { animate as motionAnimate, stagger } from "motion"; + +type AnimationTarget = string | Element | Element[] | NodeList | null; + +let isClosing = false; + +export async function closePopup() { + if (isClosing) return; + isClosing = true; + + const background = document.getElementById("whatsnewbk"); + const popup = document.getElementsByClassName("whatsnewContainer")[0] as + | HTMLElement + | undefined; + + if (!background || !popup) { + isClosing = false; + return; + } + + if (!settingsState.animations) { + background.remove(); + isClosing = false; + return; + } + + await (motionAnimate as any)( + [popup, background], + { opacity: [1, 0], scale: [1, 0.95] }, + { duration: 0.25, easing: [0.22, 0.03, 0.26, 1] }, + ); + + background.remove(); + isClosing = false; +} + +interface OpenPopupOptions { + header?: Node | null; + content?: (Node | null | undefined)[]; + animateSelector?: AnimationTarget; +} + +export function openPopup({ + header, + content = [], + animateSelector = ".whatsnewTextContainer *", +}: OpenPopupOptions = {}) { + const background = document.createElement("div"); + background.id = "whatsnewbk"; + background.classList.add("whatsnewBackground"); + + const container = document.createElement("div"); + container.classList.add("whatsnewContainer"); + + if (header) container.append(header); + for (const node of content) if (node) container.append(node); + + const closeButton = document.createElement("div"); + closeButton.id = "whatsnewclosebutton"; + container.append(closeButton); + + background.append(container); + document.getElementById("container")!.append(background); + + if (settingsState.animations) { + (motionAnimate as any)( + [container, background], + { scale: [0, 1] }, + { type: "spring", stiffness: 220, damping: 18 }, + ); + + if (animateSelector) { + const targets = + typeof animateSelector === "string" + ? document.querySelectorAll(animateSelector) + : animateSelector; + + (motionAnimate as any)( + targets!, + { opacity: [0, 1], y: [10, 0] }, + { + delay: stagger(0.05, { startDelay: 0.1 }), + duration: 0.5, + easing: [0.22, 0.03, 0.26, 1], + }, + ); + } + } + + delete settingsState.justupdated; + + background.addEventListener("click", (event) => { + if (event.target === background) void closePopup(); + }); + + closeButton.addEventListener("click", () => void closePopup()); +}