Merge pull request #201 from MotorTruck1221/bareSwitch

Implement Bare Server Switching
This commit is contained in:
rift 2024-01-03 18:40:52 -06:00 committed by GitHub
commit 5c632642d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1349 additions and 1174 deletions

View file

@ -14,6 +14,7 @@
<script src="/uv/uv.bundle.js"></script> <script src="/uv/uv.bundle.js"></script>
<script src="/uv/uv.config.js"></script> <script src="/uv/uv.config.js"></script>
<script src="/dynamic/dynamic.config.js"></script> <script src="/dynamic/dynamic.config.js"></script>
<script src="/localforage/localforage.min.js" defer></script>
<script> <script>
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
window.addEventListener("load", () => { window.addEventListener("load", () => {

View file

@ -21,6 +21,7 @@
"framer-motion": "^10.16.16", "framer-motion": "^10.16.16",
"i18next": "^23.7.9", "i18next": "^23.7.9",
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
"localforage": "^1.10.0",
"million": "^2.6.4", "million": "^2.6.4",
"preact": "^10.13.1", "preact": "^10.13.1",
"preact-iso": "^2.3.2", "preact-iso": "^2.3.2",

19
pnpm-lock.yaml generated
View file

@ -35,6 +35,9 @@ dependencies:
i18next-browser-languagedetector: i18next-browser-languagedetector:
specifier: ^7.2.0 specifier: ^7.2.0
version: 7.2.0 version: 7.2.0
localforage:
specifier: ^1.10.0
version: 1.10.0
million: million:
specifier: ^2.6.4 specifier: ^2.6.4
version: 2.6.4 version: 2.6.4
@ -3231,6 +3234,10 @@ packages:
engines: {node: '>= 4'} engines: {node: '>= 4'}
dev: true dev: true
/immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
dev: false
/import-fresh@3.3.0: /import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -3623,6 +3630,12 @@ packages:
type-check: 0.4.0 type-check: 0.4.0
dev: true dev: true
/lie@3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
dependencies:
immediate: 3.0.6
dev: false
/light-my-request@5.11.0: /light-my-request@5.11.0:
resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==} resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==}
dependencies: dependencies:
@ -3645,6 +3658,12 @@ packages:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true dev: true
/localforage@1.10.0:
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
dependencies:
lie: 3.1.1
dev: false
/locate-path@6.0.0: /locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'} engines: {node: '>=10'}

View file

@ -3,11 +3,39 @@ importScripts("/uv/uv.config.js");
importScripts(__uv$config.sw || "/uv/uv.sw.js"); importScripts(__uv$config.sw || "/uv/uv.sw.js");
importScripts("/dynamic/dynamic.config.js"); importScripts("/dynamic/dynamic.config.js");
importScripts("/dynamic/dynamic.worker.js"); importScripts("/dynamic/dynamic.worker.js");
//import our IDB lib
importScripts("/localforage/localforage.min.js");
localforage.config({
driver: localforage.INDEXEDDB,
name: "Nebula",
version: 1.0,
storeName: "nebula_config",
description: "Nebula Config for things reliant on IndexedDB"
});
const sw = new UVServiceWorker(); const dynPromise = new Promise(async (resolve) => {
const dynamic = new Dynamic(); try {
const bare =
(await localforage.getItem("bare")) || location.origin + "/bare/";
self.__dynamic$config.bare.path = bare;
self.dynamic = new Dynamic(self.__dynamic$config);
} catch (error) {
console.log(error);
}
resolve();
});
self.dynamic = dynamic; const uvPromise = new Promise(async (resolve) => {
try {
const bare =
(await localforage.getItem("bare")) || location.origin + "/bare/";
self.__uv$config.bare = bare;
self.uv = new UVServiceWorker(self.__uv$config);
} catch (error) {
console.log(error);
}
resolve();
});
self.addEventListener("fetch", (event) => { self.addEventListener("fetch", (event) => {
if ( if (
@ -15,16 +43,25 @@ self.addEventListener("fetch", (event) => {
) { ) {
event.respondWith( event.respondWith(
(async function () { (async function () {
if (await dynamic.route(event)) { try {
return await dynamic.fetch(event); await dynPromise;
} catch (error) {}
if (await self.dynamic.route(event)) {
return await self.dynamic.fetch(event);
} }
await fetch(event.request);
return await fetch(event.request);
})() })()
); );
} else if ( } else if (
event.request.url.startsWith(location.origin + __uv$config.prefix) event.request.url.startsWith(location.origin + self.__uv$config.prefix)
) { ) {
event.respondWith(sw.fetch(event)); event.respondWith(
(async function () {
try {
await uvPromise;
} catch (error) {}
return await self.uv.fetch(event);
})()
);
} }
}); });

View file

@ -50,6 +50,10 @@
"title": "Search Engine", "title": "Search Engine",
"subtitle": "Choose your search engine" "subtitle": "Choose your search engine"
}, },
"bare": {
"title": "Bare Server",
"subtitle": "Enter the URL of your bare server"
},
"theme": { "theme": {
"title": "Theme", "title": "Theme",
"subtitle": "Choose a theme so your eyes don't hate us" "subtitle": "Choose a theme so your eyes don't hate us"

View file

@ -70,7 +70,7 @@ export function Home() {
type="text" type="text"
value={inputValue} value={inputValue}
onChange={handleInputChange} onChange={handleInputChange}
className={`font-roboto h-14 rounded-t-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none text-input-text ${ className={`font-roboto h-14 rounded-t-2xl border border-input-border-color bg-input p-2 text-center text-xl text-input-text placeholder:text-input-text focus:outline-none ${
isFocused && inputValue.trim() !== "" isFocused && inputValue.trim() !== ""
? "w-10/12 md:w-3/12" ? "w-10/12 md:w-3/12"
: "w-80 rounded-2xl" : "w-80 rounded-2xl"

View file

@ -0,0 +1,50 @@
import { useState, useEffect } from "preact/hooks";
import { set } from "../../util/IDB";
import { uninstallServiceWorkers } from "../../util/SWHelper";
interface BareInputProps {
placeholder: string;
storageKey: string;
}
function BareInput(props: BareInputProps) {
const value = localStorage.getItem(props.storageKey) || "/bare/";
const [inputValue, setInputValue] = useState(value);
function validateUrl(url: string) {
let finalUrl = url;
if (url === "/bare/" || url === "/bare") {
finalUrl = "/bare/";
return finalUrl;
}
if (url === null || url === undefined || url === "") {
finalUrl = "/bare/";
return finalUrl;
}
if (!url.endsWith("/")) {
finalUrl = url + "/";
}
if (!finalUrl.startsWith("http://") && !finalUrl.startsWith("https://")) {
finalUrl = "https://" + finalUrl;
}
return finalUrl;
}
function handleChange(event: any) {
const url = validateUrl(event.target.value);
setInputValue(event.target.value);
set(props.storageKey, url);
localStorage.setItem(props.storageKey, url);
uninstallServiceWorkers();
window.location.reload();
}
return (
<input
type="text"
placeholder={props.placeholder}
value={inputValue}
onBlur={handleChange}
className="font-roboto flex h-14 w-56 flex-row rounded-2xl border border-input-border-color bg-input p-4 text-center text-xl"
/>
);
}
export default BareInput;

View file

@ -48,7 +48,7 @@ const Dropdown = ({
{options.map((option, index) => ( {options.map((option, index) => (
<div <div
key={option.id} key={option.id}
className={`border border-input-border-color bg-input p-2 hover:bg-dropdown-option-hover-color text-input-text ${ className={`border border-input-border-color bg-input p-2 text-input-text hover:bg-dropdown-option-hover-color ${
index === options.length - 1 ? "rounded-b-2xl" : "" index === options.length - 1 ? "rounded-b-2xl" : ""
}`} }`}
onClick={() => { onClick={() => {

View file

@ -1,6 +1,7 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { tabContentVariant, settingsPageVariant } from "./Variants"; import { tabContentVariant, settingsPageVariant } from "./Variants";
import Dropdown from "./Dropdown"; import Dropdown from "./Dropdown";
import BareInput from "./BareInput";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const Proxy = ({ id, active }) => { const Proxy = ({ id, active }) => {
@ -73,6 +74,15 @@ const Proxy = ({ id, active }) => {
refresh={false} refresh={false}
/> />
</div> </div>
<div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-7 text-center">
<div className="p-2 text-3xl font-bold text-input-text">
{t("settings.bare.title")}
</div>
<div className="text-md p-4 font-bold text-input-text">
{t("settings.bare.subtitle")}
</div>
<BareInput placeholder="/bare/" storageKey="bare" />
</div>
</motion.div> </motion.div>
</motion.div> </motion.div>
); );

View file

@ -18,10 +18,12 @@ export function DiscordPage() {
<p className="font-roboto text-4xl font-bold text-input-text"> <p className="font-roboto text-4xl font-bold text-input-text">
{t("discord.title")} {t("discord.title")}
</p> </p>
<span className="font-roboto text-3xl text-input-text">{t("discord.sub")}</span> <span className="font-roboto text-3xl text-input-text">
{t("discord.sub")}
</span>
</div> </div>
<a href="https://discord.gg/unblocker" className="p-6"> <a href="https://discord.gg/unblocker" className="p-6">
<button className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none text-input-text"> <button className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl text-input-text placeholder:text-input-text focus:outline-none">
{t("discord.button1")} {t("discord.button1")}
</button> </button>
</a> </a>
@ -33,7 +35,7 @@ export function DiscordPage() {
}} }}
className="p-6" className="p-6"
> >
<button className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none text-input-text"> <button className="font-roboto h-14 w-56 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl text-input-text placeholder:text-input-text focus:outline-none">
{t("discord.button2")} {t("discord.button2")}
</button> </button>
</a> </a>

22
src/util/IDB.js Normal file
View file

@ -0,0 +1,22 @@
function set(key, value) {
localforage.config({
driver: localforage.INDEXEDDB,
name: "Nebula",
version: 1.0,
storeName: "nebula_config",
description: "Nebula Config for things reliant on IndexedDB"
});
localforage.setItem(key, value);
}
async function get(key) {
localforage.config({
driver: localforage.INDEXEDDB,
name: "Nebula",
version: 1.0,
storeName: "nebula_config",
description: "Nebula Config for things reliant on IndexedDB"
});
return await localforage.getItem(key);
}
export { set, get };

19
src/util/SWHelper.js Normal file
View file

@ -0,0 +1,19 @@
function updateServiceWorkers() {
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
registration.update();
console.log("Service Worker Updated");
}
});
}
function uninstallServiceWorkers() {
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
registration.unregister();
console.log("Service Worker Unregistered");
}
});
}
export { updateServiceWorkers, uninstallServiceWorkers };

View file

@ -4,6 +4,8 @@ import preact from "@preact/preset-vite";
import { viteStaticCopy } from "vite-plugin-static-copy"; import { viteStaticCopy } from "vite-plugin-static-copy";
import { uvPath } from "@nebula-services/ultraviolet"; import { uvPath } from "@nebula-services/ultraviolet";
import { dynamicPath } from "@nebula-services/dynamic"; import { dynamicPath } from "@nebula-services/dynamic";
import path from "path";
const __dirname = path.resolve();
console.log(dynamicPath); console.log(dynamicPath);
@ -22,6 +24,14 @@ export default defineConfig({
src: `${dynamicPath}/dynamic.*.js`.replace(/\\/g, "/"), src: `${dynamicPath}/dynamic.*.js`.replace(/\\/g, "/"),
dest: "dynamic", dest: "dynamic",
overwrite: false overwrite: false
},
{
src: `${__dirname}/node_modules/localforage/dist/localforage.*.js`.replace(
/\\/g,
"/"
),
dest: "localforage",
overwrite: false
} }
] ]
}), }),