Merge pull request #201 from MotorTruck1221/bareSwitch
Implement Bare Server Switching
This commit is contained in:
commit
5c632642d4
27 changed files with 1349 additions and 1174 deletions
|
|
@ -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", () => {
|
||||||
|
|
|
||||||
|
|
@ -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
19
pnpm-lock.yaml
generated
|
|
@ -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'}
|
||||||
|
|
|
||||||
55
public/sw.js
55
public/sw.js
|
|
@ -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);
|
||||||
|
})()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
50
src/pages/Settings/BareInput.tsx
Normal file
50
src/pages/Settings/BareInput.tsx
Normal 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;
|
||||||
|
|
@ -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={() => {
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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
22
src/util/IDB.js
Normal 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
19
src/util/SWHelper.js
Normal 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 };
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue