feat: add webui, zip builder
This commit is contained in:
parent
94040e020f
commit
4c71eef936
97
create_zip.sh
Executable file
97
create_zip.sh
Executable file
@ -0,0 +1,97 @@
|
||||
version=$(grep "version=" module/module.prop | cut -d "=" -f 2)
|
||||
|
||||
echo "BeeSrv ZIP Builder"
|
||||
echo "=================="
|
||||
echo ""
|
||||
|
||||
# Check if zip is installed
|
||||
if ! command -v zip &> /dev/null; then
|
||||
echo "[!] zip is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if bun is installed
|
||||
if ! command -v bun &> /dev/null; then
|
||||
echo "[!] bun is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if filename to be created already exists
|
||||
if [ -f "BeeSrv-$version.zip" ]; then
|
||||
echo "[i] BeeSrv-$version.zip already exists, would you like to overwrite it? (y/n)"
|
||||
read overwrite
|
||||
if [ "$overwrite" != "y" ]; then
|
||||
echo "[!] Aborting..."
|
||||
exit 1
|
||||
else
|
||||
rm -rf BeeSrv-$version.zip
|
||||
echo "[✔] Overwriting BeeSrv-$version.zip..."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for leftover tmp dir
|
||||
if [ -d "tmp" ]; then
|
||||
echo "[i] tmp directory already exists, would you like to overwrite it? (y/n)"
|
||||
read overwrite
|
||||
if [ "$overwrite" != "y" ]; then
|
||||
echo "[!] Aborting..."
|
||||
exit 1
|
||||
else
|
||||
rm -rf tmp
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copy module to tmp
|
||||
cp -r module tmp
|
||||
echo "[✔] Created working directory"
|
||||
|
||||
# Clean any unnecessary files
|
||||
rm -rf tmp/module/webroot/dist
|
||||
rm -rf tmp/module/webroot/.gitignore
|
||||
rm -rf tmp/module/webroot/package-lock.json
|
||||
echo "[✔] Completed cleanup"
|
||||
|
||||
# Build webroot
|
||||
echo "[i] Building webroot..."
|
||||
cd tmp/webroot
|
||||
echo "[i] Installing dependencies..."
|
||||
bun install
|
||||
echo ""
|
||||
echo "[✔] Installed dependencies"
|
||||
echo ""
|
||||
echo "[i] Building with parcel..."
|
||||
echo ""
|
||||
bunx parcel build src/index.html
|
||||
echo ""
|
||||
echo "[✔] Built webroot"
|
||||
|
||||
# Clean up for zip
|
||||
rm -rf .parcel-cache
|
||||
rm -rf src
|
||||
rm -rf node_modules
|
||||
rm bun.lock*
|
||||
rm package*
|
||||
rm .gitignore
|
||||
echo "[✔] Completed cleanup"
|
||||
|
||||
# Move built files to webroot
|
||||
cd ..
|
||||
cp -r webroot/dist/* webroot
|
||||
echo "[✔] Moved built files to webroot"
|
||||
|
||||
# Remove build dir
|
||||
rm -rf webroot/dist
|
||||
echo "[✔] Completed cleanup"
|
||||
|
||||
# Create zip
|
||||
echo "[i] Creating zip..."
|
||||
zip -r ../BeeSrv-$version.zip *
|
||||
cd ..
|
||||
echo "[✔] Created zip"
|
||||
|
||||
# Clean up
|
||||
rm -rf tmp
|
||||
echo "[✔] Completed cleanup"
|
||||
|
||||
echo ""
|
||||
echo "BeeSrv-$version.zip created successfully!"
|
@ -2,7 +2,8 @@ ui_print ""
|
||||
ui_print "=== BEESRV ==="
|
||||
ui_print "Version: $(grep_prop version $MODPATH/module.prop)"
|
||||
ui_print "Made with ❤️ by ihatenodejs"
|
||||
ui_print "================================"
|
||||
ui_print "==========================="
|
||||
ui_print ""
|
||||
sleep 0.4
|
||||
|
||||
# Environment checks
|
||||
@ -31,14 +32,33 @@ fi
|
||||
# Create config
|
||||
ui_print "[i] Creating config..."
|
||||
mkdir -p /data/adb/beesrv
|
||||
touch /data/adb/beesrv/config.txt
|
||||
chmod 664 /data/adb/beesrv/config.txt
|
||||
|
||||
echo "SERVER=" >> /data/adb/beesrv/config.txt
|
||||
# Check if config file exists, and check if required variables are set
|
||||
config_modified=false
|
||||
if [ ! -f "/data/adb/beesrv/config.txt" ]; then
|
||||
echo "SERVER=" >> /data/adb/beesrv/config.txt
|
||||
ui_print "[✔] Config created"
|
||||
ui_print ""
|
||||
else
|
||||
ui_print "[i] Config file found, checking..."
|
||||
|
||||
ui_print "[✔] Config created"
|
||||
# Check SERVER var
|
||||
if ! grep -q "SERVER=" /data/adb/beesrv/config.txt; then
|
||||
ui_print "[i] SERVER variable not found, adding..."
|
||||
echo "SERVER=" >> /data/adb/beesrv/config.txt
|
||||
config_modified=true
|
||||
fi
|
||||
|
||||
if [ "$config_modified" = true ]; then
|
||||
ui_print "[✔] Config modified successfully"
|
||||
ui_print ""
|
||||
else
|
||||
ui_print "[✔] Config already valid, skipping update..."
|
||||
ui_print ""
|
||||
fi
|
||||
fi
|
||||
|
||||
ui_print ""
|
||||
ui_print "== INSTALLATION COMPLETE! =="
|
||||
ui_print ""
|
||||
ui_print "Join our Telegram channel: t.me/pontushub"
|
||||
sleep 0.4
|
5
module/webroot/.gitignore
vendored
Normal file
5
module/webroot/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.parcel-cache/
|
||||
dist/
|
||||
node_modules/
|
||||
package-lock.json
|
||||
bun.lock*
|
25
module/webroot/package.json
Normal file
25
module/webroot/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "parcel-vanilla-starter",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"source": "src/index.html",
|
||||
"scripts": {
|
||||
"start": "parcel",
|
||||
"build": "bunx @tailwindcss/cli -i ./src/css/style-pre.css -o ./src/css/style.css && parcel build",
|
||||
"build:css:watch": "bunx @tailwindcss/cli -i ./src/css/style-pre.css -o ./src/css/style.css --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/cli": "^4.1.3",
|
||||
"kernelsu": "^1.0.6",
|
||||
"tailwindcss": "^4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"events": "^3.3.0",
|
||||
"os-browserify": "^0.3.0",
|
||||
"parcel": "^2.14.0",
|
||||
"process": "^0.11.10",
|
||||
"util": "^0.12.5",
|
||||
"vm-browserify": "^1.1.2"
|
||||
}
|
||||
}
|
1
module/webroot/src/css/style-pre.css
Normal file
1
module/webroot/src/css/style-pre.css
Normal file
@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
409
module/webroot/src/css/style.css
Normal file
409
module/webroot/src/css/style.css
Normal file
@ -0,0 +1,409 @@
|
||||
/*! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com */
|
||||
@layer properties;
|
||||
@layer theme, base, components, utilities;
|
||||
@layer theme {
|
||||
:root, :host {
|
||||
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
|
||||
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||
"Courier New", monospace;
|
||||
--color-red-400: oklch(70.4% 0.191 22.216);
|
||||
--color-green-400: oklch(79.2% 0.209 151.711);
|
||||
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||
--color-slate-500: oklch(55.4% 0.046 257.417);
|
||||
--color-slate-600: oklch(44.6% 0.043 257.281);
|
||||
--color-slate-700: oklch(37.2% 0.044 257.287);
|
||||
--color-gray-300: oklch(87.2% 0.01 258.338);
|
||||
--color-gray-600: oklch(44.6% 0.03 256.802);
|
||||
--color-gray-700: oklch(37.3% 0.034 259.733);
|
||||
--color-gray-800: oklch(27.8% 0.033 256.848);
|
||||
--color-gray-900: oklch(21% 0.034 264.665);
|
||||
--color-white: #fff;
|
||||
--spacing: 0.25rem;
|
||||
--text-xl: 1.25rem;
|
||||
--text-xl--line-height: calc(1.75 / 1.25);
|
||||
--text-2xl: 1.5rem;
|
||||
--text-2xl--line-height: calc(2 / 1.5);
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
--radius-md: 0.375rem;
|
||||
--animate-spin: spin 1s linear infinite;
|
||||
--default-transition-duration: 150ms;
|
||||
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--default-font-family: var(--font-sans);
|
||||
--default-mono-font-family: var(--font-mono);
|
||||
}
|
||||
}
|
||||
@layer base {
|
||||
*, ::after, ::before, ::backdrop, ::file-selector-button {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0 solid;
|
||||
}
|
||||
html, :host {
|
||||
line-height: 1.5;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
tab-size: 4;
|
||||
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
|
||||
font-feature-settings: var(--default-font-feature-settings, normal);
|
||||
font-variation-settings: var(--default-font-variation-settings, normal);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
hr {
|
||||
height: 0;
|
||||
color: inherit;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
abbr:where([title]) {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
-webkit-text-decoration: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
b, strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
code, kbd, samp, pre {
|
||||
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
|
||||
font-feature-settings: var(--default-mono-font-feature-settings, normal);
|
||||
font-variation-settings: var(--default-mono-font-variation-settings, normal);
|
||||
font-size: 1em;
|
||||
}
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
sub, sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
table {
|
||||
text-indent: 0;
|
||||
border-color: inherit;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
:-moz-focusring {
|
||||
outline: auto;
|
||||
}
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
ol, ul, menu {
|
||||
list-style: none;
|
||||
}
|
||||
img, svg, video, canvas, audio, iframe, embed, object {
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
img, video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
button, input, select, optgroup, textarea, ::file-selector-button {
|
||||
font: inherit;
|
||||
font-feature-settings: inherit;
|
||||
font-variation-settings: inherit;
|
||||
letter-spacing: inherit;
|
||||
color: inherit;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
opacity: 1;
|
||||
}
|
||||
:where(select:is([multiple], [size])) optgroup {
|
||||
font-weight: bolder;
|
||||
}
|
||||
:where(select:is([multiple], [size])) optgroup option {
|
||||
padding-inline-start: 20px;
|
||||
}
|
||||
::file-selector-button {
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
::placeholder {
|
||||
opacity: 1;
|
||||
}
|
||||
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
|
||||
::placeholder {
|
||||
color: currentcolor;
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
::-webkit-date-and-time-value {
|
||||
min-height: 1lh;
|
||||
text-align: inherit;
|
||||
}
|
||||
::-webkit-datetime-edit {
|
||||
display: inline-flex;
|
||||
}
|
||||
::-webkit-datetime-edit-fields-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
|
||||
padding-block: 0;
|
||||
}
|
||||
:-moz-ui-invalid {
|
||||
box-shadow: none;
|
||||
}
|
||||
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
|
||||
appearance: button;
|
||||
}
|
||||
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
[hidden]:where(:not([hidden="until-found"])) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@layer utilities {
|
||||
.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: calc(var(--spacing) * 4);
|
||||
}
|
||||
.mr-1 {
|
||||
margin-right: calc(var(--spacing) * 1);
|
||||
}
|
||||
.mr-2 {
|
||||
margin-right: calc(var(--spacing) * 2);
|
||||
}
|
||||
.mb-2 {
|
||||
margin-bottom: calc(var(--spacing) * 2);
|
||||
}
|
||||
.mb-4 {
|
||||
margin-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
.ml-2 {
|
||||
margin-left: calc(var(--spacing) * 2);
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.table {
|
||||
display: table;
|
||||
}
|
||||
.h-4 {
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
.h-5 {
|
||||
height: calc(var(--spacing) * 5);
|
||||
}
|
||||
.w-4 {
|
||||
width: calc(var(--spacing) * 4);
|
||||
}
|
||||
.w-5 {
|
||||
width: calc(var(--spacing) * 5);
|
||||
}
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.transform {
|
||||
transform: var(--tw-rotate-x) var(--tw-rotate-y) var(--tw-rotate-z) var(--tw-skew-x) var(--tw-skew-y);
|
||||
}
|
||||
.animate-spin {
|
||||
animation: var(--animate-spin);
|
||||
}
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
.gap-2 {
|
||||
gap: calc(var(--spacing) * 2);
|
||||
}
|
||||
.rounded-md {
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
.border {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
.border-gray-600 {
|
||||
border-color: var(--color-gray-600);
|
||||
}
|
||||
.bg-gray-700 {
|
||||
background-color: var(--color-gray-700);
|
||||
}
|
||||
.bg-gray-800 {
|
||||
background-color: var(--color-gray-800);
|
||||
}
|
||||
.bg-gray-900 {
|
||||
background-color: var(--color-gray-900);
|
||||
}
|
||||
.bg-slate-500 {
|
||||
background-color: var(--color-slate-500);
|
||||
}
|
||||
.bg-slate-600 {
|
||||
background-color: var(--color-slate-600);
|
||||
}
|
||||
.p-2 {
|
||||
padding: calc(var(--spacing) * 2);
|
||||
}
|
||||
.p-4 {
|
||||
padding: calc(var(--spacing) * 4);
|
||||
}
|
||||
.px-3 {
|
||||
padding-inline: calc(var(--spacing) * 3);
|
||||
}
|
||||
.px-4 {
|
||||
padding-inline: calc(var(--spacing) * 4);
|
||||
}
|
||||
.py-1 {
|
||||
padding-block: calc(var(--spacing) * 1);
|
||||
}
|
||||
.py-2 {
|
||||
padding-block: calc(var(--spacing) * 2);
|
||||
}
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
.text-2xl {
|
||||
font-size: var(--text-2xl);
|
||||
line-height: var(--tw-leading, var(--text-2xl--line-height));
|
||||
}
|
||||
.font-bold {
|
||||
--tw-font-weight: var(--font-weight-bold);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
.font-semibold {
|
||||
--tw-font-weight: var(--font-weight-semibold);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
.text-gray-300 {
|
||||
color: var(--color-gray-300);
|
||||
}
|
||||
.text-green-400 {
|
||||
color: var(--color-green-400);
|
||||
}
|
||||
.text-red-400 {
|
||||
color: var(--color-red-400);
|
||||
}
|
||||
.text-white {
|
||||
color: var(--color-white);
|
||||
}
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
.outline {
|
||||
outline-style: var(--tw-outline-style);
|
||||
outline-width: 1px;
|
||||
}
|
||||
.transition-colors {
|
||||
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||
}
|
||||
.hover\:bg-slate-600 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-slate-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-slate-700 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-slate-700);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: rotateX(0);
|
||||
}
|
||||
@property --tw-rotate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: rotateY(0);
|
||||
}
|
||||
@property --tw-rotate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: rotateZ(0);
|
||||
}
|
||||
@property --tw-skew-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: skewX(0);
|
||||
}
|
||||
@property --tw-skew-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: skewY(0);
|
||||
}
|
||||
@property --tw-border-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: solid;
|
||||
}
|
||||
@property --tw-font-weight {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-outline-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: solid;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@layer properties {
|
||||
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
||||
*, ::before, ::after, ::backdrop {
|
||||
--tw-rotate-x: rotateX(0);
|
||||
--tw-rotate-y: rotateY(0);
|
||||
--tw-rotate-z: rotateZ(0);
|
||||
--tw-skew-x: skewX(0);
|
||||
--tw-skew-y: skewY(0);
|
||||
--tw-border-style: solid;
|
||||
--tw-font-weight: initial;
|
||||
--tw-outline-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
104
module/webroot/src/index.html
Normal file
104
module/webroot/src/index.html
Normal file
@ -0,0 +1,104 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BeeSrv WebUI</title>
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
|
||||
<script type="module" src="js/app.js"></script>
|
||||
</head>
|
||||
<body class="bg-gray-900 text-white">
|
||||
<header class="bg-gray-800 p-4">
|
||||
<h1 class="text-2xl font-bold">BeeSrv WebUI</h1>
|
||||
</header>
|
||||
|
||||
<main class="p-4">
|
||||
<h2 class="text-2xl font-bold mb-4">Self-Check</h2>
|
||||
<table class="w-full bg-gray-700 border-collapse border border-gray-600 mb-4">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="border border-gray-600 p-2 text-left">Internet Connection</th>
|
||||
<td class="border border-gray-600 p-2">
|
||||
<button class="bg-slate-500 text-white px-3 py-1 rounded-md hover:bg-slate-600 transition-colors" id="checkConnection">
|
||||
<span id="testBtn" class="flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-router-icon lucide-router w-4 h-4"><rect width="20" height="8" x="2" y="14" rx="2"/><path d="M6.01 18H6"/><path d="M10.01 18H10"/><path d="M15 10v4"/><path d="M17.84 7.17a4 4 0 0 0-5.66 0"/><path d="M20.66 4.34a8 8 0 0 0-11.31 0"/></svg>
|
||||
Test
|
||||
</span>
|
||||
<span id="testBtnLoading" class="flex items-center gap-2 hidden">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-loader-icon lucide-loader w-4 h-4 animate-spin"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>
|
||||
Testing...
|
||||
</span>
|
||||
</button>
|
||||
<span id="connectionStatus" class="ml-2 text-green-400 flex items-center gap-2 hidden">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-icon lucide-check w-5 h-5"><path d="M20 6 9 17l-5-5"/></svg>
|
||||
Connected
|
||||
</span>
|
||||
<span id="connectionError" class="ml-2 text-red-400 flex items-center gap-2 hidden">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x w-5 h-5"><path d="M18 6 6 18"/><path d="M6 6l12 12"/></svg>
|
||||
Error
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="errorBox" class="bg-gray-700 border border-gray-600 p-4 rounded-md mb-4 hidden">
|
||||
<div class="flex items-center gap-2 text-red-400 mb-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-alert-triangle w-5 h-5"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
|
||||
<span class="font-semibold">Error</span>
|
||||
</div>
|
||||
<p id="errorMessage" class="text-gray-300">No error</p>
|
||||
</div>
|
||||
|
||||
<h2 class="text-2xl font-bold mb-4">Module</h2>
|
||||
<table class="w-full bg-gray-700 border-collapse border border-gray-600">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="border border-gray-600 p-2 text-left">Version</th>
|
||||
<td class="border border-gray-600 p-2">
|
||||
<span id="version" class="flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-loader-icon lucide-loader w-5 h-5 animate-spin" id="versionLoader"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>
|
||||
<span id="versionText">Loading...</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="border border-gray-600 p-2 text-left">Server</th>
|
||||
<td class="border border-gray-600 p-2">
|
||||
<span id="server" class="flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-loader-icon lucide-loader w-5 h-5 animate-spin" id="serverLoader"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>
|
||||
<span id="serverText">Loading...</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 class="text-2xl font-bold mt-4">Join Us</h2>
|
||||
<div class="flex flex-wrap gap-2 mt-4">
|
||||
<a href="https://t.me/pontushub">
|
||||
<button class="flex items-center bg-slate-600 text-white px-4 py-2 rounded-md hover:bg-slate-700 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-send-icon lucide-send mr-1 w-5 h-5"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/></svg>
|
||||
Telegram
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://t.me/pontushubchat">
|
||||
<button class="flex items-center bg-slate-600 text-white px-4 py-2 rounded-md hover:bg-slate-700 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle-question-icon lucide-message-circle-question mr-1 w-5 h-5"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
|
||||
Support
|
||||
</button>
|
||||
</a>
|
||||
<a href="https://donate.stripe.com/cN28yxe1wf5teC4dQS">
|
||||
<button class="flex items-center bg-slate-600 text-white px-4 py-2 rounded-md hover:bg-slate-700 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins mr-1 w-5 h-5"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg>
|
||||
Donate
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<p class="mt-4 text-center">Made with ❤️ by ihatenodejs</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
146
module/webroot/src/js/app.js
Normal file
146
module/webroot/src/js/app.js
Normal file
@ -0,0 +1,146 @@
|
||||
import { exec } from "kernelsu"
|
||||
|
||||
const modules_dir = "/data/adb/modules/BeeSrv"
|
||||
const persist_dir = "/data/adb/beesrv"
|
||||
|
||||
function showError(message) {
|
||||
const errorBox = document.getElementById("errorBox")
|
||||
const errorMessage = document.getElementById("errorMessage")
|
||||
errorMessage.textContent = message
|
||||
errorBox.classList.remove("hidden")
|
||||
}
|
||||
|
||||
function hideError() {
|
||||
const errorBox = document.getElementById("errorBox")
|
||||
errorBox.classList.add("hidden")
|
||||
}
|
||||
|
||||
async function getVersion() {
|
||||
try {
|
||||
const { errno, stdout, stderr } = await exec(`cat ${modules_dir}/module.prop`)
|
||||
if (errno !== 0) {
|
||||
showError("Failed to read module version")
|
||||
return "Unknown"
|
||||
}
|
||||
const version = stdout.split("\n").find(line => line.startsWith("version="))
|
||||
if (!version) {
|
||||
showError("Module version not found")
|
||||
return "Unknown"
|
||||
}
|
||||
return version.split("=")[1]
|
||||
} catch (error) {
|
||||
showError("Error reading module version")
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
async function getServer() {
|
||||
try {
|
||||
const { errno, stdout, stderr } = await exec(`cat ${persist_dir}/config.txt`)
|
||||
if (errno !== 0) {
|
||||
showError("Failed to read server configuration")
|
||||
return "Unknown"
|
||||
}
|
||||
const server = stdout.split("\n").find(line => line.startsWith("SERVER="))
|
||||
if (!server) {
|
||||
showError("Server configuration not found")
|
||||
return "Unknown"
|
||||
}
|
||||
return server.split("=")[1]
|
||||
} catch (error) {
|
||||
showError("Error reading server configuration")
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
async function checkConnection() {
|
||||
try {
|
||||
const response = await fetch('https://httpbin.org/get', {
|
||||
method: 'GET',
|
||||
signal: AbortSignal.timeout(5000)
|
||||
});
|
||||
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
if (error.name === 'AbortError') {
|
||||
throw new Error('Connection check timed out. Please try again.');
|
||||
} else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {
|
||||
throw new Error('Unable to reach the internet. Please check your network connection.');
|
||||
} else {
|
||||
throw new Error('Connection check failed. Please try again later.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
const versionText = document.getElementById("versionText")
|
||||
const serverText = document.getElementById("serverText")
|
||||
const versionLoader = document.getElementById("versionLoader")
|
||||
const serverLoader = document.getElementById("serverLoader")
|
||||
|
||||
try {
|
||||
const version = await getVersion()
|
||||
const server = await getServer()
|
||||
|
||||
versionLoader.classList.add("hidden")
|
||||
serverLoader.classList.add("hidden")
|
||||
versionText.textContent = version
|
||||
serverText.textContent = server
|
||||
} catch (error) {
|
||||
versionLoader.classList.add("hidden")
|
||||
serverLoader.classList.add("hidden")
|
||||
versionText.textContent = "Error"
|
||||
serverText.textContent = "Error"
|
||||
}
|
||||
|
||||
const checkConnectionBtn = document.getElementById("checkConnection")
|
||||
const testBtn = document.getElementById("testBtn")
|
||||
const testBtnLoading = document.getElementById("testBtnLoading")
|
||||
const connectionStatus = document.getElementById("connectionStatus")
|
||||
const connectionError = document.getElementById("connectionError")
|
||||
|
||||
function resetButtonState() {
|
||||
testBtnLoading.classList.add("hidden")
|
||||
testBtn.classList.remove("hidden")
|
||||
checkConnectionBtn.disabled = false
|
||||
}
|
||||
|
||||
function setLoadingState() {
|
||||
testBtn.classList.add("hidden")
|
||||
testBtnLoading.classList.remove("hidden")
|
||||
connectionStatus.classList.add("hidden")
|
||||
connectionError.classList.add("hidden")
|
||||
checkConnectionBtn.disabled = true
|
||||
hideError()
|
||||
}
|
||||
|
||||
function showSuccessState() {
|
||||
connectionStatus.classList.remove("hidden")
|
||||
connectionError.classList.add("hidden")
|
||||
// Hide the button after successful test
|
||||
checkConnectionBtn.classList.add("hidden")
|
||||
}
|
||||
|
||||
function showErrorState(message) {
|
||||
connectionStatus.classList.add("hidden")
|
||||
connectionError.classList.remove("hidden")
|
||||
showError(message)
|
||||
checkConnectionBtn.classList.add("hidden")
|
||||
}
|
||||
|
||||
checkConnectionBtn.addEventListener("click", async () => {
|
||||
setLoadingState()
|
||||
try {
|
||||
const isConnected = await checkConnection()
|
||||
resetButtonState()
|
||||
if (isConnected) {
|
||||
showSuccessState()
|
||||
} else {
|
||||
showErrorState("No internet connection detected")
|
||||
}
|
||||
} catch (error) {
|
||||
resetButtonState()
|
||||
showErrorState(error.message)
|
||||
}
|
||||
})
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user