diff --git a/packages/beta-switch/.gitignore b/packages/beta-switch/.gitignore new file mode 100644 index 000000000..b67fef920 --- /dev/null +++ b/packages/beta-switch/.gitignore @@ -0,0 +1,3 @@ +/dist/ +/node_modules/ +/tsconfig.tsbuildinfo diff --git a/packages/beta-switch/README.md b/packages/beta-switch/README.md new file mode 100644 index 000000000..d4b0a342e --- /dev/null +++ b/packages/beta-switch/README.md @@ -0,0 +1,8 @@ +# beta-switch +For switching between two sites running in the same domain + + +## Scripts + +- `yarn run build`: Builds the project +- `yarn run dev`: Builds the project & watches files for changes, triggering a rebuild diff --git a/packages/beta-switch/package.json b/packages/beta-switch/package.json new file mode 100644 index 000000000..651426d5a --- /dev/null +++ b/packages/beta-switch/package.json @@ -0,0 +1,16 @@ +{ + "name": "@thunderstore/beta-switch", + "version": "0.1.0", + "description": "Small thing for switching between two projects running in the same domain", + "repository": "https://github.com/thunderstore-io/thunderstore-ui/tree/master/packages/beta-switch", + "main": "dist/thunderstore-beta-switch.cjs.js", + "module": "dist/thunderstore-beta-switch.esm.js", + "types": "dist/thunderstore-beta-switch.cjs.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "tsc --watch" + } +} diff --git a/packages/beta-switch/src/index.ts b/packages/beta-switch/src/index.ts new file mode 100644 index 000000000..b56f5e6bd --- /dev/null +++ b/packages/beta-switch/src/index.ts @@ -0,0 +1,137 @@ +const enabledPages = ["/communities", "c/[^/]+/?$"]; + +const legacy = { + protocol: "http://", + hostname: "thunderstore.temp", + port: "", +}; + +const beta = { + protocol: "http://", + hostname: "new.thunderstore.temp", + port: "", +}; + +function setCookie(key: string, value: string) { + const date = new Date(); + date.setFullYear(date.getFullYear() + 1); + document.cookie = `${key}=${value}; expires=${date.toUTCString()}; path=/`; +} + +function checkBetaRedirect() { + let betaIsAvailable = false; + enabledPages.forEach((regPath) => { + const regExecuted = new RegExp(regPath).exec(window.location.pathname); + const found = regExecuted !== null && regExecuted.length < 2; + if (!betaIsAvailable && found) { + betaIsAvailable = true; + } + }, betaIsAvailable); + + const desireCookie = new RegExp("betaDesire=([^;]+);").exec( + document.cookie[-1] === ";" ? document.cookie : document.cookie + ";" + )?.[1]; + console.log("betaDesire:", desireCookie); + + if (!desireCookie) { + setCookie("betaDesire", "legacy"); + } + let userDesiredProject = legacy; + if (desireCookie === "beta") { + userDesiredProject = beta; + } + + // const wouldBeRedirect = `${userDesiredProject.protocol}${userDesiredProject.hostname}${userDesiredProject.port !== "" ? ":" : ""}${userDesiredProject.port}${window.location.pathname}${window.location.search}`; + // console.log("would be redirect", wouldBeRedirect); + // const legacyRedirect = `${legacy.protocol}${legacy.hostname}${legacy.port !== "" ? ":" : ""}${legacy.port}${window.location.pathname}${window.location.search}`; + // console.log("legacy redirect", legacyRedirect); + + // const currentUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port !== "" ? ":" : ""}${window.location.port}`; + // const desiredUrl = `${userDesiredProject.protocol}${userDesiredProject.hostname}${userDesiredProject.port !== "" ? ":" : ""}${userDesiredProject.port}`; + + // console.log("currentUrl", currentUrl); + // console.log("desiredUrl", desiredUrl); + if (betaIsAvailable) { + if ( + `${window.location.protocol}//${window.location.hostname}${ + window.location.port !== "" ? ":" : "" + }${window.location.port}` !== + `${userDesiredProject.protocol}${userDesiredProject.hostname}${ + userDesiredProject.port !== "" ? ":" : "" + }${userDesiredProject.port}` + ) { + console.log("redirecting desired"); + window.location.replace( + `${userDesiredProject.protocol}${userDesiredProject.hostname}${ + userDesiredProject.port !== "" ? ":" : "" + }${userDesiredProject.port}${window.location.pathname}${ + window.location.search + }` + ); + } + // "else" user is on desired and available page + } else { + console.log("redirecting to legacy"); + window.location.replace( + `${legacy.protocol}${legacy.hostname}${legacy.port !== "" ? ":" : ""}${ + legacy.port + }${window.location.pathname}${window.location.search}` + ); + } + // console.log("not redirecting"); +} + +async function insertSwitchBar() { + const bar = document.createElement("div"); + bar.setAttribute( + "style", + "position:relative;top:0;width:100%;display: flex;padding: 6px 8px;justify-content: center;align-items: center;gap: 8px;align-self: stretch;background:#3498DB;font-family: Lato;font-size: 13px;font-style: normal;font-weight: 700;color: #FFF;" + ); + + bar.innerHTML = + ''; + + const text = document.createElement("p"); + text.setAttribute("style", "line-height: 140%"); + text.innerHTML = + "There’s a new beta version of this page available. Want to take it for a spin?"; + + const switchToBetaButton = document.createElement("button"); + switchToBetaButton.setAttribute( + "style", + "display:flex;padding:6px 8px;justify-content:center;align-items:center;gap:12px;border-radius:6px;border:1px solid #FFF;background:transparent;" + ); + switchToBetaButton.onclick = () => { + setCookie("betaDesire", "beta"); + checkBetaRedirect(); + }; + switchToBetaButton.innerHTML = "Switch to beta"; + + const ignoreBarButton = document.createElement("button"); + ignoreBarButton.setAttribute( + "style", + "color:#FFF;position:absolute;right:16px;height:16px;width:16px;background:transparent;fill:#FFF;" + ); + ignoreBarButton.onclick = () => { + setCookie("hideBetaBar", "hide"); + }; + ignoreBarButton.innerHTML = + ''; + + bar.appendChild(text); + bar.appendChild(switchToBetaButton); + bar.appendChild(ignoreBarButton); + await new Promise((r) => setTimeout(r, 1000)); + document.body.insertBefore(bar, document.body.firstChild); +} + +const hideBetaBarCookie = new RegExp("hideBetaBar=([^;]+);").exec( + document.cookie[-1] === ";" ? document.cookie : document.cookie + ";" +)?.[1]; +console.log("hideBetaBar:", hideBetaBarCookie); +if (hideBetaBarCookie !== "hide") { + insertSwitchBar(); +} +console.log("inserted switch bar"); +checkBetaRedirect(); +console.log("checked beta"); diff --git a/packages/beta-switch/tsconfig.json b/packages/beta-switch/tsconfig.json new file mode 100644 index 000000000..51e494b37 --- /dev/null +++ b/packages/beta-switch/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "node", + "removeComments": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true, + "composite": true, + "outDir": "./dist", + "rootDir": "./src", + "jsx": "react-jsx" + }, + "include": ["./src/**/*.tsx", "./src/**/*.ts"], + "exclude": ["node_modules"] +}