Merge pull request #235 from MotorTruck1221/bugfixes

Bugfixes
This commit is contained in:
rift 2024-03-21 15:28:37 -05:00 committed by GitHub
commit a46908389c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 966 additions and 393 deletions

5
.dockerignore Normal file
View file

@ -0,0 +1,5 @@
node_modules/
.vscode
npm-debug.log
yarn-error.log
.github/

14
Dockerfile Normal file
View file

@ -0,0 +1,14 @@
FROM node:21-alpine
WORKDIR /app
COPY package*.json .
COPY . .
RUN npm i -g pnpm
RUN pnpm install
RUN pnpm run build
EXPOSE 8080
CMD ["pnpm", "start"]

13
docker-compose.yml Normal file
View file

@ -0,0 +1,13 @@
version: "3"
services:
nebula:
image: nebula:latest
build:
context: .
dockerfile: Dockerfile
container_name: nebula
restart: unless-stopped
ports:
# Host:Container (DO NOT MODIFY THE CONTAINER PORT)
- "8081:8080"

View file

@ -4,12 +4,31 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="/epoxy/index.js" defer></script> <script src="/epoxy/index.js" defer></script>
<script src="/libcurl/index.cjs" defer></script> <script src="/libcurl/index.js" defer></script>
<script src="/transports/bareTransport.js" defer></script> <script src="/transports/bareTransport.js" defer></script>
<script src="/uv/uv.bundle.js" defer></script> <script src="/uv/uv.bundle.js" defer></script>
<script src="/uv/uv.config.js" defer></script> <script src="/uv/uv.config.js" defer></script>
<script src="/dynamic/dynamic.config.js" defer></script> <script src="/dynamic/dynamic.config.js" defer></script>
<script src="/localforage/localforage.min.js" defer></script> <script src="/localforage/localforage.min.js" defer></script>
<script>
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/sw.js", {
scope: "/~/"
})
.then(() => {
console.log("Service Worker Registered");
try {
window.setTransport();
} catch {}
})
.catch((err) => {
console.error("Service Worker Failed to Register", err);
});
});
}
</script>
</head> </head>
<body style="margin: 0"> <body style="margin: 0">
<div id="app"></div> <div id="app"></div>
@ -22,10 +41,15 @@
window.location.href = window.location.href; window.location.href = window.location.href;
</script> </script>
<script> <script>
if (!localStorage["auth"] && new URL(document.all.rcheck.href).password) { try {
window.location.reload(); if (
localStorage["auth"] = 1; !localStorage["auth"] &&
} new URL(document.all.rcheck.href).password
) {
window.location.reload();
localStorage["auth"] = 1;
}
} catch {}
</script> </script>
</body> </body>
</html> </html>

View file

@ -16,7 +16,7 @@
"@fastify/static": "^6.12.0", "@fastify/static": "^6.12.0",
"@mercuryworkshop/bare-mux": "^1.0.5", "@mercuryworkshop/bare-mux": "^1.0.5",
"@mercuryworkshop/epoxy-transport": "^1.1.0", "@mercuryworkshop/epoxy-transport": "^1.1.0",
"@mercuryworkshop/libcurl-transport": "^1.2.1", "@mercuryworkshop/libcurl-transport": "^1.2.4",
"@nebula-services/dynamic": "0.7.2-patch.2", "@nebula-services/dynamic": "0.7.2-patch.2",
"@titaniumnetwork-dev/ultraviolet": "^3.0.0", "@titaniumnetwork-dev/ultraviolet": "^3.0.0",
"@tomphttp/bare-server-node": "2.0.3", "@tomphttp/bare-server-node": "2.0.3",
@ -29,16 +29,16 @@
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"express": "^4.18.3", "express": "^4.19.1",
"fastify": "^4.26.2", "fastify": "^4.26.2",
"framer-motion": "^10.18.0", "framer-motion": "^10.18.0",
"i18next": "^23.10.1", "i18next": "^23.10.1",
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"million": "^2.6.4", "million": "^2.6.4",
"preact": "^10.19.6", "preact": "^10.20.0",
"preact-iso": "^2.4.0", "preact-iso": "^2.4.0",
"preact-render-to-string": "^6.4.0", "preact-render-to-string": "^6.4.1",
"preact-router": "^4.1.2", "preact-router": "^4.1.2",
"rammerhead": "https://github.com/NebulaServices/rammerhead/releases/download/rammerhead-1.2.41-nebula.8/rammerhead-1.2.41-nebula.7.tgz", "rammerhead": "https://github.com/NebulaServices/rammerhead/releases/download/rammerhead-1.2.41-nebula.8/rammerhead-1.2.41-nebula.7.tgz",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
@ -46,21 +46,21 @@
"react-icons": "^4.12.0", "react-icons": "^4.12.0",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
"tsx": "^4.7.1", "tsx": "^4.7.1",
"wisp-server-node": "^1.0.2", "wisp-server-node": "^1.0.4",
"ws": "^8.16.0" "ws": "^8.16.0"
}, },
"devDependencies": { "devDependencies": {
"@preact/preset-vite": "^2.8.1", "@preact/preset-vite": "^2.8.2",
"autoprefixer": "^10.4.18", "autoprefixer": "^10.4.19",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-preact": "^1.3.0", "eslint-config-preact": "^1.3.0",
"postcss": "^8.4.35", "postcss": "^8.4.38",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.12", "prettier-plugin-tailwindcss": "^0.5.12",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5.4.2", "typescript": "^5.4.3",
"vite": "^5.1.5", "vite": "^5.2.2",
"vite-plugin-static-copy": "^1.0.1" "vite-plugin-static-copy": "^1.0.1"
} }
} }

1043
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
importScripts("/epoxy/index.js"); importScripts("/epoxy/index.js");
importScripts("/libcurl/index.cjs"); importScripts("/libcurl/index.js");
importScripts("/transports/bareTransport.js"); importScripts("/transports/bareTransport.js");
importScripts("/uv/uv.bundle.js"); importScripts("/uv/uv.bundle.js");
importScripts("/uv/uv.config.js"); importScripts("/uv/uv.config.js");

View file

@ -14,8 +14,8 @@ export function HeaderButton(props: HeaderButtonProps) {
return ( return (
<Link href={href} className="flex h-full w-full bg-navbar-color sm:h-auto"> <Link href={href} className="flex h-full w-full bg-navbar-color sm:h-auto">
<div className="group flex w-full flex-row items-center justify-center border-t-2 border-solid border-navbar-text-color p-4 md:border-none"> <div className="group flex w-full flex-row items-center justify-center border-t-2 border-solid border-navbar-text-color p-4 md:border-none">
<Icon className="h-10 w-10 text-text-color transition duration-500 group-hover:text-text-hover-color md:h-6 md:w-6" /> <Icon className="h-6 w-6 text-text-color transition duration-500 group-hover:text-text-hover-color md:h-6 md:w-6" />
<span className="font-roboto pl-1 text-center text-4xl font-bold text-text-color transition duration-500 group-hover:text-text-hover-color md:text-lg"> <span className="font-roboto pl-1 text-center text-3xl font-bold text-text-color transition duration-500 group-hover:text-text-hover-color md:text-lg">
{t(translationKey)} {t(translationKey)}
</span> </span>
</div> </div>

View file

@ -8,6 +8,8 @@ import prod from "./config.json"; // Set prod to true if you wish to load balanc
import { enc } from "../aes"; import { enc } from "../aes";
import CloakedHead from "../util/CloakedHead"; import CloakedHead from "../util/CloakedHead";
import { useEffect } from "preact/hooks"; import { useEffect } from "preact/hooks";
import { setTransport } from "../util/transports";
import { updateServiceWorkers } from "../util/SWHelper.js";
export function Home() { export function Home() {
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);
@ -18,6 +20,10 @@ export function Home() {
const handleLoad = () => { const handleLoad = () => {
const firstLoad = localStorage.getItem("firstLoad") || "true"; const firstLoad = localStorage.getItem("firstLoad") || "true";
console.log(firstLoad); console.log(firstLoad);
//make sure service workers are updated
updateServiceWorkers();
//make sure transport is set
//setTransport();
if (firstLoad == "true" && prod) { if (firstLoad == "true" && prod) {
function changeBare(url: string) { function changeBare(url: string) {
set("bare", url); set("bare", url);
@ -86,6 +92,8 @@ export function Home() {
const handleSubmit = (event) => { const handleSubmit = (event) => {
event.preventDefault(); event.preventDefault();
//ensure transport is set
setTransport();
window.location.href = window.location.href =
"/go/" + "/go/" +
encodeURIComponent( encodeURIComponent(

View file

@ -1,8 +1,11 @@
import { HeaderRoute } from "../components/HeaderRoute"; import { HeaderRoute } from "../components/HeaderRoute";
import { setTransport } from "../util/transports";
interface Window { interface Window {
__uv$config: any; __uv$config: any;
} }
export function Radon() { export function Radon() {
//make sure there is a transport set
setTransport();
return ( return (
<HeaderRoute> <HeaderRoute>
<iframe <iframe

View file

@ -17,7 +17,7 @@ const CloakPreset = (props: Props) => {
return ( return (
<div <div
onClick={cloak} onClick={cloak}
className="cursor-pointer rounded-full border border-input-border-color bg-lighter" className="flex h-16 w-16 cursor-pointer rounded-full border border-input-border-color bg-lighter"
> >
<img <img
src={props.faviconUrl === "none" ? "/logo.png" : props.faviconUrl} src={props.faviconUrl === "none" ? "/logo.png" : props.faviconUrl}

View file

@ -4,8 +4,8 @@ import Dropdown from "./Dropdown";
import BareInput from "./BareInput"; import BareInput from "./BareInput";
import WispInput from "./WispInput"; import WispInput from "./WispInput";
import ProxyInput from "./ProxyInput"; import ProxyInput from "./ProxyInput";
import { changeTransport } from "../../util/transports";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import TransportDropdown from "./transportDropdown";
const Proxy = ({ id, active }) => { const Proxy = ({ id, active }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -118,10 +118,10 @@ const Proxy = ({ id, active }) => {
<div className="text-md p-4 font-bold text-input-text"> <div className="text-md p-4 font-bold text-input-text">
Select the transport to use Select the transport to use
</div> </div>
<Dropdown <TransportDropdown
storageKey="transport" storageKey="transport"
options={transports} options={transports}
refresh={true} refresh={false}
/> />
</div> </div>
</motion.div> </motion.div>

View file

@ -26,7 +26,7 @@ const TabSettings = ({ id, active }) => {
<div className="text-md pb-5 font-bold text-input-text"> <div className="text-md pb-5 font-bold text-input-text">
{t("settings.cloaking.subtitle")} {t("settings.cloaking.subtitle")}
</div> </div>
<div className="flex flex-row space-x-4"> <div className="flex flex-row flex-wrap items-center justify-center gap-4">
<CloakPreset faviconUrl="none" title="none" /> <CloakPreset faviconUrl="none" title="none" />
<CloakPreset <CloakPreset
faviconUrl="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=32" faviconUrl="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://google.com&size=32"

View file

@ -0,0 +1,80 @@
import { FaAngleDown } from "react-icons/fa";
import { useState, useEffect } from "preact/hooks";
import { changeTransport } from "../../util/transports.ts";
const wispUrl =
localStorage.getItem("wispUrl") ||
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/wisp/";
interface Option {
id: string;
label: string; // Translations CAN be passed
}
const TransportDropdown = ({
storageKey,
options,
refresh
}: {
storageKey: string;
options: Option[];
refresh: boolean;
}) => {
const [isOpen, setIsOpen] = useState(false);
const [choice, setChoice] = useState(() => {
return localStorage.getItem(storageKey) || options[0]?.id || "";
});
// update on localstorage change
useEffect(() => {
setChoice(localStorage.getItem(storageKey) || options[0]?.id || "");
}, [storageKey, options]);
return (
<div className="relative text-center">
<div
className={`font-roboto flex h-14 w-56 cursor-pointer flex-col items-center justify-center border border-input-border-color bg-input text-center text-xl ${
isOpen ? "rounded-t-2xl" : "rounded-2xl"
}`}
onClick={() => setIsOpen(!isOpen)}
>
<div className="flex h-full w-full select-none flex-row items-center">
<div className="h-full w-1/4"></div>
<div className="flex w-2/4 flex-col items-center text-input-text">
{options.find((o) => o.id === choice)?.label}
</div>
<div className="flex w-1/4 flex-col items-center text-input-text">
<FaAngleDown />
</div>
</div>
{isOpen && (
<div className="absolute top-full w-full">
{options.map((option, index) => (
<div
key={option.id}
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" : ""
}`}
onClick={() => {
setIsOpen(false);
setChoice(option.id);
localStorage.setItem(storageKey, option.id);
changeTransport(option.id, wispUrl);
if (refresh === true) {
window.location.reload();
}
}}
>
{option.label}
</div>
))}
</div>
)}
</div>
</div>
);
};
export default TransportDropdown;

View file

@ -13,14 +13,16 @@ export function NotFound() {
originalFavicon="/logo.png" originalFavicon="/logo.png"
/> />
<section className="h-full"> <section className="h-full">
<div className="flex h-full flex-col items-center justify-center"> <div className="flex h-full flex-col items-center justify-center text-center">
<img src="/404.png" className="h-72"></img> <img src="/404.png" className="h-72"></img>
<div className="flex flex-col items-center p-6"> <div className="flex flex-col items-center p-6">
<p className="font-roboto text-4xl font-bold">{t("404.text")}</p> <p className="font-roboto text-4xl font-bold text-text-color">
<span className="font-roboto text-3xl">404</span> {t("404.text")}
</p>
<span className="font-roboto text-3xl text-text-color">404</span>
</div> </div>
<Link href="/"> <Link href="/">
<button className="font-roboto h-14 w-44 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl placeholder:text-input-text focus:outline-none"> <button className="font-roboto h-14 w-44 rounded-2xl border border-input-border-color bg-input p-2 text-center text-xl text-text-color placeholder:text-input-text focus:outline-none">
{t("404.return")} {t("404.return")}
</button> </button>
</Link> </Link>

View file

@ -7,23 +7,25 @@ import { Radon } from "./pages/Radon";
import { Settings } from "./pages/Settings/"; import { Settings } from "./pages/Settings/";
import { AboutBlank } from "./AboutBlank"; import { AboutBlank } from "./AboutBlank";
import { Faq } from "./pages/Faq"; import { Faq } from "./pages/Faq";
//import { setTransport } from "./util/transports.js";
import "./style.css"; import "./style.css";
import "./i18n"; import "./i18n";
import { setTransport } from "./util/transports";
export default function Routes() { export default function Routes() {
if ("serviceWorker" in navigator) { //if ("serviceWorker" in navigator) {
window.addEventListener("load", () => { //window.addEventListener("load", () => {
navigator.serviceWorker // navigator.serviceWorker
.register("/sw.js", { // .register("/sw.js", {
scope: "/~/" // scope: "/~/"
}) // })
.then(() => { // .then(() => {
console.log("Service worker registered successfully"); // console.log("Service worker registered successfully");
}); // setTransport();
}); // });
} //});
//}
return ( return (
<LocationProvider> <LocationProvider>
<Router> <Router>

View file

@ -1,3 +1,5 @@
import { setTransport } from "./transports.ts";
function updateServiceWorkers() { function updateServiceWorkers() {
navigator.serviceWorker.getRegistrations().then(function (registrations) { navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) { for (let registration of registrations) {
@ -16,4 +18,17 @@ function uninstallServiceWorkers() {
}); });
} }
export { updateServiceWorkers, uninstallServiceWorkers }; function registerServiceWorker() {
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("/sw.js", {
scope: "/~/"
})
.then(() => {
console.log("Service worker registered successfully");
setTransport();
});
}
}
export { updateServiceWorkers, uninstallServiceWorkers, registerServiceWorker };

View file

@ -2,6 +2,13 @@ import {
SetTransport, SetTransport,
registerRemoteListener registerRemoteListener
} from "@mercuryworkshop/bare-mux"; } from "@mercuryworkshop/bare-mux";
//import { isIOS } from "./IosDetector";
declare global {
interface Window {
setTransport: () => void;
}
}
function changeTransport(transport: string, wispUrl: string) { function changeTransport(transport: string, wispUrl: string) {
switch (transport) { switch (transport) {
@ -15,7 +22,7 @@ function changeTransport(transport: string, wispUrl: string) {
console.log("Setting transport to Libcurl"); console.log("Setting transport to Libcurl");
SetTransport("CurlMod.LibcurlClient", { SetTransport("CurlMod.LibcurlClient", {
wisp: wispUrl, wisp: wispUrl,
wasm: "https://cdn.jsdelivr.net/npm/libcurl.js@v0.5.2/libcurl.wasm" wasm: "https://cdn.jsdelivr.net/npm/libcurl.js@v0.5.3/libcurl.wasm"
}); });
break; break;
case "bare": case "bare":
@ -29,7 +36,7 @@ function changeTransport(transport: string, wispUrl: string) {
default: default:
SetTransport("CurlMod.LibcurlClient", { SetTransport("CurlMod.LibcurlClient", {
wisp: wispUrl, wisp: wispUrl,
wasm: "/libcurl.wasm" wasm: "https://cdn.jsdelivr.net/npm/libcurl.js@v0.5.3/libcurl.wasm"
}); });
break; break;
} }
@ -45,10 +52,32 @@ const wispUrl =
"/wisp/"; "/wisp/";
registerRemoteListener(navigator.serviceWorker.controller!); registerRemoteListener(navigator.serviceWorker.controller!);
//if (isIOS) {
// console.log("iOS device detected. Bare will be used.");
// changeTransport(
// localStorage.getItem("transport") || "libcurl",
// localStorage.getItem("wispUrl") || wispUrl
// );
//} else {
// changeTransport(
// localStorage.getItem("transport") || "bare",
// localStorage.getItem("wispUrl") || wispUrl
// );
//}
changeTransport( //changeTransport(
localStorage.getItem("transport") || "libcurl", // localStorage.getItem("transport") || "libcurl",
localStorage.getItem("wispUrl") || wispUrl // localStorage.getItem("wispUrl") || wispUrl
); //);
export { changeTransport, getTransport }; // helper function for ../routes.tsx
function setTransport() {
changeTransport(
localStorage.getItem("transport") || "libcurl",
localStorage.getItem("wispUrl") || wispUrl
);
}
window.setTransport = setTransport;
export { changeTransport, getTransport, setTransport };

View file

@ -7,6 +7,9 @@ import { dynamicPath } from "@nebula-services/dynamic";
import { epoxyPath } from "@mercuryworkshop/epoxy-transport"; import { epoxyPath } from "@mercuryworkshop/epoxy-transport";
import { libcurlPath } from "@mercuryworkshop/libcurl-transport"; import { libcurlPath } from "@mercuryworkshop/libcurl-transport";
import path from "path"; import path from "path";
import { createBareServer } from "@tomphttp/bare-server-node";
import wisp from "wisp-server-node";
import http from "http";
const __dirname = path.resolve(); const __dirname = path.resolve();
export default defineConfig({ export default defineConfig({
@ -48,10 +51,16 @@ export default defineConfig({
], ],
server: { server: {
proxy: { proxy: {
"/bare": { "/bare/": {
target: "http://localhost:8080/", target: "http://localhost:8080/",
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/bare/, "") rewrite: (path) => path.replace(/^\/bare\//, "")
},
"/wisp/": {
target: "http://ruby.rubynetwork.co/wisp/",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(/^\/wisp\//, "")
} }
} }
} }