diff --git a/package.json b/package.json index 06bc7fdf..6d8d768e 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "astro-compressor": "^0.4.1", "astro-icon": "^0.8.1", "astro-lazy-youtube-embed": "^0.5.4", + "classnames": "^2.5.1", "platform": "^1.3.6", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/public/_redirects b/public/_redirects index 776f769b..02cb2f24 100644 --- a/public/_redirects +++ b/public/_redirects @@ -19,7 +19,7 @@ /gitbook-access https://app.gitbook.com/invite/-MhmG2mhIIHTtQPuHV_k/acNI2LAF6LtdJW06t4Hc /devserver https://discord.gg/N3XKxzTrq3 /dev https://audacity.gitbook.io/dev/ -/nightly /beta +/nightly /next /au4win https://nightly.link/audacity/audacity/workflows/au4_build_windows/master /au4mac https://nightly.link/audacity/audacity/workflows/au4_build_macos/master /au4lin https://nightly.link/audacity/audacity/workflows/au4_build_linux/master @@ -29,6 +29,11 @@ /) / /vpat /VPAT.pdf +# prerelease +/au4 /next 301 +/alpha /next 301 +/beta /next 301 + # campaign links /survey https://docs.google.com/forms/d/e/1FAIpQLSd42XPhC69bKUA9kbYiTXboRLaj9Q11_BUEXTK0v0TzWJQmDQ/viewform?usp=dialog /audacitypromo https://www.youtube.com/watch?v=Lb7jx4wdXXE&mtm_campaign=audacityapp&mtm_content=welcomescreen_video diff --git a/src/assets/data/audacityReleases.ts b/src/assets/data/audacityReleases.ts index e90982bf..f4948119 100644 --- a/src/assets/data/audacityReleases.ts +++ b/src/assets/data/audacityReleases.ts @@ -1,16 +1,16 @@ export type ReleaseInfo = { name: string; browser_download_url: string; - checksum: string; + checksum?: string; type: string; }; -type ReleaseDirectory = { +export type ReleaseDirectory = { version: string; win: ReleaseInfo[]; mac: ReleaseInfo[]; lin: ReleaseInfo[]; - src: ReleaseInfo[]; + src?: ReleaseInfo[]; }; export const audacityReleases: ReleaseDirectory = { @@ -127,4 +127,161 @@ export const audacityReleases: ReleaseDirectory = { type: ".tar.gz", }, ], -}; \ No newline at end of file +}; + +export const hasDownloadAssets = (downloads?: ReleaseDirectory): boolean => { + if (!downloads) { + return false; + } + + const { win, mac, lin, src } = downloads; + + return Boolean( + (win && win.length) + || (mac && mac.length) + || (lin && lin.length) + || (src && src.length), + ); +}; + +export type PreReleaseEntry = { + id: string; + label: string; + isActive: boolean; + summary: string; + pageHref: string; + downloads: ReleaseDirectory; +}; + +export const alphaPreRelease: PreReleaseEntry = { + id: "alpha", + label: "Alpha", + isActive: true, + summary: + "Get an early look at the next major release. Expect unfinished features and potential bugs.", + pageHref: "/next", + downloads: { + version: "Audacity 4 Alpha 1", + win: [ + { + name: "64 bit", + browser_download_url: + "https://github.com/audacity/audacity/actions/runs/18406361889/artifacts/4237171895", + type: ".zip", + }, + ], + mac: [ + { + name: "ARM 64 zip (Apple Silicon)", + browser_download_url: + "https://github.com/audacity/audacity/actions/runs/18406354692/artifacts/4237536953", + type: ".zip", + }, + ], + lin: [ + { + name: "AppImage", + browser_download_url: + "https://github.com/audacity/audacity/actions/runs/18406368664/artifacts/4237050905", + type: ".zip", + }, + ], + src: [], + }, +}; + +export const betaPreRelease: PreReleaseEntry = { + id: "beta", + label: "Beta", + isActive: false, + summary: "Help us test upcoming features before they ship.", + pageHref: "/next", + downloads: { + version: "3.5.0 beta", + win: [ + { + name: "64 bit installer (recommended)", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-64bit.exe", + checksum: + "ed7de964ed11cbc8f74e815dbcb2cb8487ba136818cf1a148f16cadd4c10f3d0", + type: ".exe", + }, + { + name: "64 bit zip file", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-64bit.zip", + checksum: + "52da5c3e2507408d72c4ab425c2e465e3c8ad452b2ac89ddfb3f5bc141d68a03", + type: ".zip", + }, + { + name: "32 bit installer", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-32bit.exe", + checksum: + "6bb6c0d3513be7d98c400f43d84cd39992065f4c6460d80b6cb1667733ca95c7", + type: ".exe", + }, + { + name: "32 bit zip file", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-32bit.zip", + checksum: + "c313ca3c475b487bf88a42537cbc9454090391250017fe210226b3ca78797d9a", + type: ".zip", + }, + ], + mac: [ + { + name: "Universal dmg (recommended)", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-macOS-3.5.0-beta-3-universal.dmg", + checksum: + "9500ede91b837fc12e5106fa33d6603829288b90fb1e28d2d70bfee9db33406e", + type: ".dmg", + }, + { + name: "ARM 64 dmg (Apple Silicon)", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-macOS-3.5.0-beta-3-arm64.dmg", + checksum: + "0f3e9b9ee8e77d8b8613db8d66927e982bbec870e801811060d3d8fbc25c7698", + type: ".dmg", + }, + { + name: "x86_64 dmg (Intel)", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-macOS-3.5.0-beta-3-x86_64.dmg", + checksum: + "415342de27b572bd3801f51bd77e850a21701b39e2392c2c347ea8db4da4f122", + type: ".dmg", + }, + ], + lin: [ + { + name: "AppImage", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-linux-3.5.0-beta-3-x64.AppImage", + checksum: + "fc5df63e3819f4f59b4366c436579bd1a73b045a4dae28316edf6c23948a06ce", + type: ".AppImage", + }, + ], + src: [ + { + name: "Source code", + browser_download_url: + "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-sources-3.5.0-beta-3.tar.gz", + checksum: + "53c33ed875f4eb1501707d7989a6de253370a368c1c50a877e5cfa96c02bebdc", + type: ".tar.gz", + }, + ], + }, +}; + +export const preReleaseList: PreReleaseEntry[] = [ + alphaPreRelease, + betaPreRelease, +]; \ No newline at end of file diff --git a/src/assets/data/betaReleases.ts b/src/assets/data/betaReleases.ts deleted file mode 100644 index 77371c77..00000000 --- a/src/assets/data/betaReleases.ts +++ /dev/null @@ -1,98 +0,0 @@ -export type ReleaseInfo = { - name: string; - browser_download_url: string; - checksum: string; - type: string; -}; - -type ReleaseDirectory = { - version: string; - win: ReleaseInfo[]; - mac: ReleaseInfo[]; - lin: ReleaseInfo[]; - src: ReleaseInfo[]; -}; - -export const betaReleases: ReleaseDirectory = { - version: "3.5.0 beta", - win: [ - { - name: "64 bit installer (recommended)", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-64bit.exe", - checksum: - "ed7de964ed11cbc8f74e815dbcb2cb8487ba136818cf1a148f16cadd4c10f3d0", - type: ".exe", - }, - { - name: "64 bit zip file", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-64bit.zip", - checksum: - "52da5c3e2507408d72c4ab425c2e465e3c8ad452b2ac89ddfb3f5bc141d68a03", - type: ".zip", - }, - { - name: "32 bit installer", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-32bit.exe", - checksum: - "6bb6c0d3513be7d98c400f43d84cd39992065f4c6460d80b6cb1667733ca95c7", - type: ".exe", - }, - { - name: "32 bit zip file", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-win-3.5.0-beta-3-32bit.zip", - checksum: - "c313ca3c475b487bf88a42537cbc9454090391250017fe210226b3ca78797d9a", - type: ".zip", - }, - ], - mac: [ - { - name: "Universal dmg (recommended)", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-macOS-3.5.0-beta-3-universal.dmg", - checksum: - "9500ede91b837fc12e5106fa33d6603829288b90fb1e28d2d70bfee9db33406e", - type: ".dmg", - }, - { - name: "ARM 64 dmg (Apple Silicon)", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-macOS-3.5.0-beta-3-arm64.dmg", - checksum: - "0f3e9b9ee8e77d8b8613db8d66927e982bbec870e801811060d3d8fbc25c7698", - type: ".dmg", - }, - { - name: "x86_64 dmg (Intel)", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-macOS-3.5.0-beta-3-x86_64.dmg", - checksum: - "415342de27b572bd3801f51bd77e850a21701b39e2392c2c347ea8db4da4f122", - type: ".dmg", - }, - ], - lin: [ - { - name: "AppImage", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-linux-3.5.0-beta-3-x64.AppImage", - checksum: - "fc5df63e3819f4f59b4366c436579bd1a73b045a4dae28316edf6c23948a06ce", - type: ".AppImage", - }, - ], - src: [ - { - name: "Source code", - browser_download_url: - "https://github.com/audacity/audacity/releases/download/Audacity-3.5.0-beta-3/audacity-sources-3.5.0-beta-3.tar.gz", - checksum: - "53c33ed875f4eb1501707d7989a6de253370a368c1c50a877e5cfa96c02bebdc", - type: ".tar.gz", - }, - ], -}; diff --git a/src/assets/data/promotions.ts b/src/assets/data/promotions.ts new file mode 100644 index 00000000..ef0db169 --- /dev/null +++ b/src/assets/data/promotions.ts @@ -0,0 +1,106 @@ +export type PromoData = { + isActive?: boolean; + priority?: number; + osTargets?: string[]; + suppressOnPaths?: string[]; + message: string; + styles?: { + container?: string; + message?: string; + button?: string; + }; + tracking?: { + category: string; + action: string; + name: string; + }; + cta?: { + text: string; + link: string; + }; +}; + +const promoData: Record = { + audacity4Alpha: { + isActive: true, + priority: 50, + suppressOnPaths: ["/next", "/download"], + message: "Want a peek at our next big release?", + cta: { + text: "Try the Audacity 4 Alpha", + link: "/next", + }, + tracking: { + category: "Promo CTA", + action: "Promo CTA button", + name: "Audacity 4 Alpha", + }, + styles: { + container: "bg-[#0f004d]", + message: "text-gray-100", + button: "bg-[#ff3254] hover:bg-[#ff1a3c] text-white", + }, + }, + voiceByAuribus: { + isActive: true, + priority: 50, + osTargets: ["Windows", "OS X"], + message: + "AI powered professional vocals. Transform any track with Voice by Auribus!", + styles: { + container: "bg-yellow-300", + message: "text-gray-900", + button: "bg-gray-100 hover:bg-white", + }, + tracking: { + category: "Promo CTA", + action: "Promo CTA button", + name: "Voice by Auribus Muse Hub", + }, + cta: { + text: "Get it on MuseHub", + link: "https://www.musehub.com/plugin/auribus?utm_source=au-web&utm_medium=au-banner&utm_campaign=au-web-mh-web-auribus", + }, + }, + ampknob: { + isActive: false, + osTargets: ["Windows", "OS X"], + message: "Heavy guitar tone in seconds. One knob, no distractions.", + styles: { + container: "bg-yellow-300", + message: "text-gray-900 font-bold", + button: + "font-bold border-2 border-gray-900 bg-gray-900 text-white hover:bg-yellow-300 hover:text-gray-900 hover:border-gray-900", + }, + tracking: { + category: "Promo CTA", + action: "Promo CTA button", + name: "Ampknob Revc Muse Hub", + }, + cta: { + text: "Try for free", + link: "https://www.musehub.com/plugin/ampknob-revc?utm_source=audacity&utm_medium=web&utm_campaign=auampknob-revc", + }, + }, + survey: { + isActive: false, + message: "3 minute survey:\nHelp us understand what features you want next", + styles: { + container: "bg-yellow-300", + message: "text-lg text-gray-900", + button: + "h-10 bg-gray-100 hover:bg-white border border-gray-900 text-gray-900", + }, + tracking: { + category: "Promo CTA", + action: "Survey CTA button", + name: "Go to Survey", + }, + cta: { + text: "Take the survey", + link: "https://docs.google.com/forms/d/e/1FAIpQLScxH_f64JPCWt5nwqa8MTPXfmi453mqYwy1xZFPF_mx9mYkNw/viewform", + }, + }, +}; + +export default promoData; diff --git a/src/components/banner/BetaBanner.jsx b/src/components/banner/BetaBanner.jsx deleted file mode 100644 index 2eff1300..00000000 --- a/src/components/banner/BetaBanner.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from "react"; -import "../../styles/icons.css"; -import { trackEvent } from "../../utils/matomo"; - -function BetaBanner(url) { - //no beta at the moment - return null; - - function handleButtonClick() { - trackEvent("Beta CTA", "Beta CTA button", "Go to Beta site"); - } - - if (url.url.endsWith("/beta/") || url.url.endsWith("/beta")) { - return null; - } else - return ( -
-
-

- Get early access to new features! -

-

- Help us test our ‘Save to cloud’ feature -

-
- { - handleButtonClick(); - }} - className="flex text-xl h-12 my-4 justify-center items-center px-4 border-2 border-gray-900 rounded-md hover:bg-gray-900 hover:text-white" - > - Join the beta - -
- ); -} - -export default BetaBanner; diff --git a/src/components/banner/PromoBanner.tsx b/src/components/banner/PromoBanner.tsx index 0bf79725..d2eb67bf 100644 --- a/src/components/banner/PromoBanner.tsx +++ b/src/components/banner/PromoBanner.tsx @@ -1,55 +1,220 @@ -import { museHubReleases } from "../../assets/data/museHubReleases"; -import "../../styles/icons.css"; +import cx from "classnames"; +import promoData from "../../assets/data/promotions"; +import type { PromoData } from "../../assets/data/promotions"; import useBrowserOS from "../../hooks/useDetectOS"; +import "../../styles/icons.css"; import { trackEvent } from "../../utils/matomo"; +import { useEffect, useMemo, useRef, useState } from "react"; + +const DEFAULT_PROMO_STYLES: NonNullable = { + container: "bg-yellow-300", + message: "text-gray-900", + button: "bg-gray-100 hover:bg-white", +}; + +const BASE_CONTAINER_CLASSNAME = + "flex flex-col lg:flex-row justify-center items-center align-start py-4 gap-3 lg:gap-6 transition-colors duration-200"; +const BASE_MESSAGE_CLASSNAME = "text-lg font-semibold"; +const BASE_BUTTON_CLASSNAME = + "flex h-8 justify-center items-center px-4 rounded-md font-semibold"; + +const PLACEHOLDER_CONTAINER_CLASSNAME = + "flex flex-col lg:flex-row justify-center items-center align-start py-4 gap-3 lg:gap-6 transition-colors duration-200 opacity-0 pointer-events-none"; + +type PromoBannerProps = { + requestPath?: string; +}; + +const STATIC_PROMOS: PromoData[] = Object.values(promoData); -function PromoBanner() { - // no promo atm - //return false; +const isPromoActive = (promo: PromoData | null | undefined) => + promo?.isActive ?? true; +const isSuppressedOnPath = (promo: PromoData, path: string | null) => { + if (!path) { + return false; + } + const suppressedPaths = promo.suppressOnPaths ?? []; + return suppressedPaths.includes(path); +}; + +const getHighestPriorityPromo = (promos: PromoData[]) => + promos.reduce((selected, current) => { + if (!current) { + return selected; + } + if (!selected) { + return current; + } + const currentPriority = current.priority ?? 0; + const selectedPriority = selected.priority ?? 0; + return currentPriority > selectedPriority ? current : selected; + }, null); + +const getEligiblePromos = (promos: PromoData[], os: string | null) => + promos.filter((promo) => { + if (!isPromoActive(promo)) { + return false; + } + if (!promo.osTargets || promo.osTargets.length === 0) { + return true; + } + if (!os) { + return false; + } + return promo.osTargets.includes(os); + }); + +const selectWeightedPromo = (promos: PromoData[]) => { + if (promos.length === 0) { + return null; + } + + const weights = promos.map((promo) => Math.max(promo.priority ?? 1, 0)); + const totalWeight = weights.reduce((sum, weight) => sum + weight, 0); + + if (totalWeight <= 0) { + return getHighestPriorityPromo(promos); + } + + let threshold = Math.random() * totalWeight; + + for (let index = 0; index < promos.length; index += 1) { + threshold -= weights[index]; + + if (threshold <= 0) { + return promos[index]; + } + } + + return promos[promos.length - 1] ?? null; +}; + +const buildPromoList = (path: string | null): PromoData[] => + STATIC_PROMOS.filter((promo) => !isSuppressedOnPath(promo, path)); + +const PromoBanner: React.FC = ({ requestPath }) => { const browserOS = useBrowserOS(); + const [selectedPromo, setSelectedPromo] = useState(null); + const [isReady, setIsReady] = useState(false); + const hasSelected = useRef(false); + const [shouldReserveSpace, setShouldReserveSpace] = useState(() => { + const pathForEval = + typeof window !== "undefined" + ? window.location.pathname + : requestPath ?? null; + const promos = buildPromoList(pathForEval); + return promos.some((promo) => isPromoActive(promo) && Boolean(promo.cta)); + }); + + const initialPath = useMemo(() => { + if (typeof window !== "undefined") { + return window.location.pathname; + } + return requestPath ?? null; + }, [requestPath]); + + useEffect(() => { + if (hasSelected.current) { + return; + } + + const pathName = + typeof window !== "undefined" ? window.location.pathname : initialPath; + + if (typeof window !== "undefined" && browserOS === null) { + return; + } + + const promos = buildPromoList(pathName); + + if (promos.length === 0) { + hasSelected.current = true; + setSelectedPromo(null); + setIsReady(true); + setShouldReserveSpace(false); + return; + } - // Only show the banner for supported OSes - const showBanner = browserOS === "OS X" || browserOS === "Windows"; + const eligiblePromos = getEligiblePromos(promos, browserOS); + const fallbackPromos = promos.filter((promo) => isPromoActive(promo)); + const selectionPool = + eligiblePromos.length > 0 ? eligiblePromos : fallbackPromos; - const getHref = () => { - if (showBanner) { - return "https://www.musehub.com/plugin/ampknob-revc?utm_source=audacity&utm_medium=web&utm_campaign=auampknob-revc"; - } else { - return "#"; // Default if OS is not supported + if (selectionPool.length === 0) { + hasSelected.current = true; + setSelectedPromo(null); + setIsReady(true); + setShouldReserveSpace(false); + return; } - }; + const promo = selectWeightedPromo(selectionPool); + hasSelected.current = true; + setSelectedPromo(promo && promo.cta ? promo : null); + setIsReady(true); + setShouldReserveSpace(true); + }, [browserOS, initialPath]); + + if (!isReady && shouldReserveSpace) { + return ( + + ); + } + + if (!isReady) { + return null; + } + + if (!selectedPromo || !selectedPromo.cta) { + return null; + } + + const { tracking, cta, message, styles } = selectedPromo; + const containerClassName = cx( + BASE_CONTAINER_CLASSNAME, + styles?.container ?? DEFAULT_PROMO_STYLES.container + ); + const messageClassName = cx( + BASE_MESSAGE_CLASSNAME, + styles?.message ?? DEFAULT_PROMO_STYLES.message + ); + const buttonClassName = cx( + BASE_BUTTON_CLASSNAME, + styles?.button ?? DEFAULT_PROMO_STYLES.button + ); + const trimmedMessage = message.trim(); function handleButtonClick() { - trackEvent("Promo CTA", "Promo CTA button", "Ampknob Revc Muse Hub"); + if (!tracking) return; + trackEvent(tracking.category, tracking.action, tracking.name); } return ( <> - {showBanner && ( -
-
-

- Heavy guitar tone in seconds. One knob, no distractions. -

+ { +
+
+

{trimmedMessage}

- Try for free + {cta.text}
- )} + } ); -} +}; export default PromoBanner; diff --git a/src/components/banner/SurveyBanner.jsx b/src/components/banner/SurveyBanner.jsx deleted file mode 100644 index 015c03ea..00000000 --- a/src/components/banner/SurveyBanner.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from "react"; -import "../../styles/icons.css"; -import { trackEvent } from "../../utils/matomo"; - -function SurveyBanner(url) { - //no survey going on at the moment - return null; - - function handleButtonClick() { - trackEvent("Survey CTA", "Survey CTA button", "Go to Survey"); - } - - return ( - - ); -} - -export default SurveyBanner; diff --git a/src/components/footer/Footer.astro b/src/components/footer/Footer.astro index 2d20ab82..2fb06bc3 100644 --- a/src/components/footer/Footer.astro +++ b/src/components/footer/Footer.astro @@ -1,5 +1,16 @@ --- import "../../styles/fonts.css"; +import { + hasDownloadAssets, + preReleaseList, +} from "../../assets/data/audacityReleases"; +const activeDownloadCampaign = preReleaseList.find((entry) => + entry.isActive && hasDownloadAssets(entry.downloads) +) ?? null; +const hasPreRelease = Boolean(activeDownloadCampaign); +const activePreReleaseAriaLabel = hasPreRelease && activeDownloadCampaign + ? `Link to ${activeDownloadCampaign.label.toLowerCase()} page` + : ""; ---
diff --git a/src/components/next/BetaDetails.astro b/src/components/next/BetaDetails.astro new file mode 100644 index 00000000..a70bba73 --- /dev/null +++ b/src/components/next/BetaDetails.astro @@ -0,0 +1,17 @@ +--- +--- +
+

+ Download the latest beta build and help us test upcoming Audacity features. +

+

+ If you'd like to help us with testing, instructions can be found below. +

+ +
diff --git a/src/env.d.ts b/src/env.d.ts index acef35f1..3af93709 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,2 +1,10 @@ /// /// + +interface ImportMetaEnv { + readonly NETLIFY_CONTEXT?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index ed444c91..bdb65ab7 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,24 +1,32 @@ --- -import Footer from "../components/footer/Footer.astro"; -import NavigationReact from "../components/navigation/NavigationReact"; +import promoData from "../assets/data/promotions"; import CookieConsent from "../components/banner/CookieConsent"; -import BetaBanner from "../components/banner/BetaBanner"; -import SurveyBanner from "../components/banner/SurveyBanner"; import PromoBanner from "../components/banner/PromoBanner"; -import useBrowserOS from "../hooks/useDetectOS"; +import Footer from "../components/footer/Footer.astro"; +import NavigationReact from "../components/navigation/NavigationReact"; export interface Props { title: string; description?: string; index?: string; + showPromoBanner?: boolean; } const { title = "Audacity | Free Audio editor, recorder, music making and more!", description = "Audacity is the world's most popular audio editing and recording app. Edit, mix, and enhance your audio tracks with the power of Audacity. Download now!", index = "all", + showPromoBanner = true, } = Astro.props; -const isNoAdPage = Astro.request.url.includes("/post-download") || Astro.request.url.includes("/au4"); +const isNoAdPage = + Astro.request.url.includes("/post-download") || + Astro.request.url.includes("/next"); +const hasActiveStaticPromo = Object.values(promoData).some((promo) => { + const isActive = promo.isActive ?? true; + return isActive && Boolean(promo.cta); +}); +const shouldShowPromoBanner = + showPromoBanner && !isNoAdPage && hasActiveStaticPromo; --- @@ -26,7 +34,7 @@ const isNoAdPage = Astro.request.url.includes("/post-download") || Astro.request - + @@ -53,9 +61,11 @@ const isNoAdPage = Astro.request.url.includes("/post-download") || Astro.request >
- {!isNoAdPage && } - {!isNoAdPage && } - {!isNoAdPage && } + { + shouldShowPromoBanner && ( + + ) + }
diff --git a/src/pages/au4.astro b/src/pages/au4.astro deleted file mode 100644 index 150c54ae..00000000 --- a/src/pages/au4.astro +++ /dev/null @@ -1,149 +0,0 @@ ---- -import BaseLayout from "../layouts/BaseLayout.astro"; -import "../styles/icons.css"; -import { betaReleases } from "../assets/data/betaReleases"; -import SplitDownloadButton from "../components/button/SplitDownloadButton.jsx"; -import FeaturedVideo from "../components/video/FeaturedVideo"; - -const { win, mac, lin } = betaReleases; ---- - - -
-
-
-

Audacity 4 Alpha 1

-
-

- The purpose of this alpha build is to test the core features of - Audacity 4 on a wide selection of hardware and operating systems. -

-

- If you experience severe issues or crashes, please file an issue on - GitHub (requires a free GitHub account). -

- - -

What's implemented

- -
    -
  • Recording and playback
  • -
  • Editing audio
  • -
  • Applying effects (destructive and real-time)
  • -
  • Exporting audio files
  • -
  • - Configuring and re-arranging the interface (including the new - Workspaces feature) -
  • -
- -

A note on compatibility ⚠️

-

- Projects saved in Audacity 4 are not backwards compatible. We - recommend you make a copy of your important projects before opening - them in Audacity 4. -

- -

Unimplemented features

-

- Some yet-to-be finalized features might appear non-functional, or - have been excluded from Audacity's interface. These are features not - yet ready for user testing, and have been disabled. -

-
    -
  • Nyquist, LADSPA and VAMP and the OpenVINO plugins
  • -
  • Preferences from Audacity 3 are not carried over
  • -
  • Envelopes and label tracks
  • -
  • Spectrogram view and the spectral editing mode
  • -
  • Most built-in effects, including generators and analyzers
  • -
  • Opening multiple projects at the same time
  • -
- -
-

Submit your feedback!

-

- We're always eager to hear what you have to say, but it's - especially important we hear from you during this early phase. - Please let us know what you think, using the following places: -

- -
-
- -
- -
-
diff --git a/src/pages/beta.astro b/src/pages/beta.astro deleted file mode 100644 index 8493d6cd..00000000 --- a/src/pages/beta.astro +++ /dev/null @@ -1,66 +0,0 @@ ---- -import BaseLayout from "../layouts/BaseLayout.astro"; -import "../styles/icons.css"; -import { betaReleases } from "../assets/data/betaReleases"; -import SplitDownloadButton from "../components/button/SplitDownloadButton.jsx"; - -const { win, mac, lin } = betaReleases; ---- - - -
-
-
-
-

Audacity Beta releases

-
-

- There currently is no beta release available. You - can download an pre-alpha version instead. -

-

- If you'd like to help us with testing, instructions can be found - below. -

- -
-
-

Audacity 4 alpha

- -

- The Audacity 4 alpha versions are unfinished at this time. This means that some buttons may not do anything yet, or placeholder - items be used. For details, check the alpha 1 page. -

-
-
-
-
diff --git a/src/pages/download.astro b/src/pages/download.astro index 1343005d..f563cd2d 100644 --- a/src/pages/download.astro +++ b/src/pages/download.astro @@ -2,14 +2,40 @@ import BaseLayout from "../layouts/BaseLayout.astro"; import OperatingSystemCard from "../components/card/OperatingSystemCard"; import "../styles/icons.css"; -import { audacityReleases } from "../assets/data/audacityReleases"; +import { + audacityReleases, + hasDownloadAssets, + preReleaseList, + type PreReleaseEntry, +} from "../assets/data/audacityReleases"; import ChecksumAccordion from "../components/accordion/ChecksumAccordion"; -const { version, src } = audacityReleases; +const { version } = audacityReleases; +const sourceDownloads = audacityReleases.src ?? []; +const primarySourceDownload = sourceDownloads[0] ?? null; +const activeDownloadEntries = preReleaseList.filter( + (entry) => entry.isActive && hasDownloadAssets(entry.downloads), +); +const hasDownloadCampaigns = activeDownloadEntries.length > 0; + +const formatCampaignLinkLabel = ( + entry: PreReleaseEntry, + platform: string, + buildName?: string, +) => + `${entry.downloads.version} for ${platform}${ + buildName ? ` (${buildName})` : "" + }`; --- - -
+ +

Downloads

@@ -48,7 +74,78 @@ const { version, src } = audacityReleases;