diff --git a/public/sw.js b/public/sw.js
new file mode 100644
index 0000000..876f1c5
--- /dev/null
+++ b/public/sw.js
@@ -0,0 +1,27 @@
+importScripts(
+ "/vu/uv.bundle.js",
+ "/vu/uv.config.js",
+ "/marcs/scramjet.shared.js",
+ "/marcs/scramjet.worker.js"
+);
+importScripts(__uv$config.sw || "/vu/uv.sw.js");
+
+const uv = new UVServiceWorker();
+const sj = new ScramjetServiceWorker();
+
+self.addEventListener("fetch", function (event) {
+ event.respondWith(
+ (async () => {
+ await sj.loadConfig();
+ if (event.request.url.startsWith(location.origin + __uv$config.prefix)) {
+ return await uv.fetch(event);
+ }
+ else if (sj.route(event)) {
+ return await sj.fetch(event);
+ }
+ else {
+ return await fetch(event.request);
+ }
+ })()
+ );
+});
diff --git a/public/vu/uv.config.js b/public/vu/uv.config.js
new file mode 100644
index 0000000..23dd015
--- /dev/null
+++ b/public/vu/uv.config.js
@@ -0,0 +1,29 @@
+self.__uv$config = {
+ prefix: "/~/uv/",
+ encodeUrl: function encode(str) {
+ if (!str) return str;
+ return encodeURIComponent(
+ str
+ .toString()
+ .split("")
+ .map((char, ind) => (ind % 2 ? String.fromCharCode(char.charCodeAt() ^ 3) : char))
+ .join("")
+ );
+ },
+ decodeUrl: function decode(str) {
+ if (!str) return str;
+ let [input, ...search] = str.split("?");
+
+ return (
+ decodeURIComponent(input)
+ .split("")
+ .map((char, ind) => (ind % 2 ? String.fromCharCode(char.charCodeAt(0) ^ 3) : char))
+ .join("") + (search.length ? "?" + search.join("?") : "")
+ );
+ },
+ handler: "/vu/uv.handler.js",
+ client: "/vu/uv.client.js",
+ bundle: "/vu/uv.bundle.js",
+ config: "/vu/uv.config.js",
+ sw: "/vu/uv.sw.js"
+};
diff --git a/src/assets/splash.json b/src/assets/splash.json
index 701a77b..34e3bfa 100644
--- a/src/assets/splash.json
+++ b/src/assets/splash.json
@@ -1,13 +1,10 @@
[
{
- "splash": "Join to our community! https://discord.gg/qsXnhSPtAK"
+ "splash": "Join our community! https://discord.gg/qsXnhSPtAK"
},
{
"splash": "Browse safely!"
},
- {
- "splash": "Hello World!"
- },
{
"splash": "Access with ease!"
},
diff --git a/src/components/Header.astro b/src/components/Header.astro
index d16ad6b..90e74d3 100644
--- a/src/components/Header.astro
+++ b/src/components/Header.astro
@@ -12,6 +12,8 @@ const path = Astro.url.pathname;
Radius
+
+
diff --git a/src/components/SettingsLoader.astro b/src/components/Loader.astro
similarity index 62%
rename from src/components/SettingsLoader.astro
rename to src/components/Loader.astro
index 0c67cd4..0bf28b8 100644
--- a/src/components/SettingsLoader.astro
+++ b/src/components/Loader.astro
@@ -1,8 +1,12 @@
diff --git a/src/env.d.ts b/src/env.d.ts
new file mode 100644
index 0000000..d5dc69e
--- /dev/null
+++ b/src/env.d.ts
@@ -0,0 +1,45 @@
+///
+///
+///
+interface SJOptions {
+ prefix: string;
+ globals?: {
+ wrapfn: string;
+ wrapthisfn: string;
+ trysetfn: string;
+ importfn: string;
+ rewritefn: string;
+ metafn: string;
+ setrealmfn: string;
+ pushsourcemapfn: string;
+ };
+ files: {
+ wasm: string;
+ shared: string;
+ worker: string;
+ client: string;
+ sync: string;
+ };
+ flags?: {
+ serviceworkers?: boolean;
+ syncxhr?: boolean;
+ naiiveRewriter?: boolean;
+ strictRewrites?: boolean;
+ rewriterLogs?: boolean;
+ captureErrors?: boolean;
+ cleanErrors?: boolean;
+ scramitize?: boolean;
+ sourcemaps?: boolean;
+ };
+ siteFlags?: {};
+ codec?: {
+ encode: string;
+ decode: string;
+ };
+}
+
+declare class ScramjetController {
+ constructor(opts: SJOptions);
+ init(): Promise;
+ encodeUrl(term: string): string;
+}
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
index 0cbf037..12109de 100644
--- a/src/layouts/Layout.astro
+++ b/src/layouts/Layout.astro
@@ -3,13 +3,13 @@ import "@styles/themes/default.css";
import "@styles/global.css";
import "@fontsource/inter";
import { ClientRouter } from "astro:transitions";
-import SettingsLoader from "@components/SettingsLoader.astro";
+import Loader from "@components/Loader.astro";
import Header from "@components/Header.astro";
---
-
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index aa8b6a8..5e19d9a 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -21,9 +21,35 @@ const randomSplash = genSplash();
-
+
-
{ randomSplash }
+
{ randomSplash }
+
+
diff --git a/src/utils/proxy.ts b/src/utils/proxy.ts
new file mode 100644
index 0000000..ca860d4
--- /dev/null
+++ b/src/utils/proxy.ts
@@ -0,0 +1,119 @@
+import { BareMuxConnection } from "@mercuryworkshop/bare-mux";
+import { StoreManager } from "./storage";
+
+const createScript = (src: string, defer?: boolean) => {
+ const script = document.createElement('script') as HTMLScriptElement;
+ script.src = src;
+ if (defer) script.defer = defer;
+ return document.body.appendChild(script);
+}
+
+/**
+ * This class automatically sets up and handles lots of stuff for us.
+ *
+ * It registers/fixes errors with SW reg
+ * It creates our bareMux worker
+ * And other stuff.
+ *
+ * @example
+ * import { SW } from "@utils/proxy.ts";
+ * const handler = new SW();
+ * //Consume the methods
+ * // Or if an instance is already running
+ * import { SW } from "@utils/proxy.ts";
+ * const handler = SW.getInstance();
+ * //Consume the methods
+*/
+class SW {
+ #baremuxConn?: BareMuxConnection;
+ #scramjetController?: ScramjetController;
+ #serviceWorker?: ServiceWorkerRegistration;
+ #storageManager: StoreManager<"radius||settings">;
+ static #instance = new Set();
+
+ static *getInstance() {
+ for (const val of SW.#instance.keys()) {
+ yield val as SW;
+ }
+ }
+
+ #search(input: string, template: string) {
+ try { return new URL(input).toString() } catch (_) {};
+
+ try {
+ const url = new URL(`http://${input}`);
+ if (url.hostname.includes(".")) return url.toString();
+ } catch (_) {};
+
+ return template.replace("%s", encodeURIComponent(input));
+ }
+
+ encodeURL(string: string, proxy: 'uv' | 'scram'): string {
+ const input = this.#search(string, "https://google.com/search?q=%s");
+ return proxy === 'uv' ? `${__uv$config.prefix}${__uv$config.encodeUrl!(input)}` : this.#scramjetController!.encodeUrl(input)
+ }
+
+ async setTransport(transport?: 'epoxy' | 'libcurl') {
+ this.#storageManager.setVal("transport", transport || this.#storageManager.getVal("transport") || 'epoxy');
+ switch(transport) {
+ case 'epoxy': {
+ await this.#baremuxConn!.setTransport("/epoxy/index.mjs", [ { wisp: 'ws://localhost:4321/wisp/' }]);
+ }
+ case 'libcurl': {
+ await this.#baremuxConn!.setTransport("/libcurl/index.mjs", [ { wisp: 'ws://localhost:4321/wisp/' }]);
+ }
+ default: {
+ await this.#baremuxConn!.setTransport("/epoxy/index.mjs", [ { wisp: 'ws://localhost:4321/wisp/' }]);
+ }
+ }
+ }
+
+ constructor() {
+ SW.#instance.add(this);
+ this.#storageManager = new StoreManager("radius||settings");
+ const checkScripts = (): Promise => {
+ return new Promise((resolve) => {
+ const t = setInterval(() => {
+ if (typeof __uv$config !== 'undefined' && typeof ScramjetController !== 'undefined') {
+ clearInterval(t);
+ resolve();
+ }
+ });
+ });
+ };
+ createScript('/vu/uv.bundle.js', true);
+ createScript('/vu/uv.config.js', true);
+ createScript('/marcs/scramjet.controller.js', true);
+
+ checkScripts().then(async () => {
+ this.#baremuxConn = new BareMuxConnection("/erab/worker.js");
+ await this.setTransport();
+ this.#scramjetController = new ScramjetController({
+ prefix: '/~/scramjet/',
+ files: {
+ wasm: "/marcs/scramjet.wasm.wasm",
+ worker: "/marcs/scramjet.worker.js",
+ client: "/marcs/scramjet.client.js",
+ shared: "/marcs/scramjet.shared.js",
+ sync: "/marcs/scramjet.sync.js"
+ },
+ flags: {
+ rewriterLogs: false
+ }
+ });
+ if ("serviceWorker" in navigator) {
+ await this.#scramjetController.init();
+ navigator.serviceWorker.ready.then(async (reg) => {
+ console.log('SW ready to go!');
+ this.#serviceWorker = reg;
+ });
+ navigator.serviceWorker.register("/sw.js", { scope: '/' });
+ }
+ else {
+ throw new Error('Your browser is not supported! This website uses Service Workers heavily.');
+ }
+ });
+ };
+}
+
+export { SW };
diff --git a/src/utils/settings.ts b/src/utils/settings.ts
index a5bc9d8..fb112c1 100644
--- a/src/utils/settings.ts
+++ b/src/utils/settings.ts
@@ -1,5 +1,6 @@
import { StoreManager } from "./storage";
-
+import { BareMuxConnection } from "@mercuryworkshop/bare-mux";
+import { SW } from "@utils/proxy.ts";
/**
* The settings class
* Initializes it's own StorageManager, and handles everything within the class itself
@@ -22,7 +23,6 @@ class Settings {
#storageManager: StoreManager<"radius||settings">;
static #instance = new Set();
-
/**
* Method to get the current or other Settings instance(s)
*
@@ -70,7 +70,7 @@ class Settings {
? document.documentElement.className = ''
: document.documentElement.className = theme || this.#storageManager.getVal('theme');
}
-
+
async *#init() {
yield this.theme(this.#storageManager.getVal('theme') || 'default');
}