mirror of
https://github.com/whosmatt/uvmod
synced 2024-11-22 07:04:07 +00:00
370 lines
13 KiB
HTML
370 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<meta property="og:title" content=UVMOD - Online Quansheng Firmware Patcher>
|
|
<meta property="og:site_name" content=UVMOD>
|
|
<meta property="og:url" content=https://whosmatt.github.io/uvmod />
|
|
<meta property="og:description"
|
|
content="Web-based tool to generate and flash customizable modded firmware, edit the configuration, and flash open source firmware for various Quansheng handheld radios.">
|
|
<meta property="og:type" content=website>
|
|
<meta property="og:image" content=https://whosmatt.github.io/uvmod/img/banner.webp>
|
|
|
|
<title>UVMOD</title>
|
|
|
|
<link rel="icon" type="image/x-icon" href="img/favicon.ico">
|
|
<!-- Custom fonts for this template-->
|
|
<link href="fonts/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
<link href="fonts/nunito.css" rel="stylesheet">
|
|
|
|
<!-- Custom styles for this template-->
|
|
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
|
|
<!-- animated gradient background and other animations-->
|
|
<style>
|
|
html {
|
|
height: 100%;
|
|
}
|
|
|
|
.bg-animated {
|
|
min-height: 100%;
|
|
background: linear-gradient(-45deg, #555555, #494949, #598647, #5cbb58);
|
|
background-size: 400% 400%;
|
|
background-attachment: fixed;
|
|
animation: gradient 5s ease;
|
|
animation-fill-mode: forwards;
|
|
}
|
|
|
|
@keyframes gradient {
|
|
0% {
|
|
background-position: 100% 50%;
|
|
}
|
|
|
|
100% {
|
|
background-position: 0% 50%;
|
|
}
|
|
}
|
|
|
|
.marquee {
|
|
display: none;
|
|
left: 0;
|
|
position: absolute;
|
|
top: 0;
|
|
z-index: 999999;
|
|
}
|
|
|
|
@keyframes fadeInFromTop {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.card-body {
|
|
animation: fadeInFromTop 1s ease-in-out;
|
|
}
|
|
|
|
@keyframes fadeInFromBottom {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(+10px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
@keyframes fadeInFromLeft {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(-20px);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.fade-in-from-bottom {
|
|
animation: fadeInFromBottom 0.7s ease-out;
|
|
}
|
|
|
|
.fade-in-from-left {
|
|
animation: fadeInFromLeft 0.7s ease-out;
|
|
}
|
|
|
|
checkbox {
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<div class="marquee">
|
|
<svg width="153px" height="69px">
|
|
<g>
|
|
<path class="logo"
|
|
d="M140.186,63.52h-1.695l-0.692,5.236h-0.847l0.77-5.236h-1.693l0.076-0.694h4.158L140.186,63.52L140.186,63.52z M146.346,68.756h-0.848v-4.545l0,0l-2.389,4.545l-1-4.545l0,0l-1.462,4.545h-0.771l1.924-5.931h0.695l0.924,4.006l2.078-4.006 h0.848V68.756L146.346,68.756z M126.027,0.063H95.352c0,0-8.129,9.592-9.654,11.434c-8.064,9.715-9.523,12.32-9.779,13.02 c0.063-0.699-0.256-3.304-3.686-13.148C71.282,8.7,68.359,0.062,68.359,0.062H57.881V0L32.35,0.063H13.169l-1.97,8.131 l14.543,0.062h3.365c9.336,0,15.055,3.747,13.467,10.354c-1.717,7.24-9.91,10.416-18.545,10.416h-3.24l4.191-17.783H10.502 L4.34,37.219h20.578c15.432,0,30.168-8.13,32.709-18.608c0.508-1.906,0.443-6.67-0.764-9.527c0-0.127-0.063-0.191-0.127-0.444 c-0.064-0.063-0.127-0.509,0.127-0.571c0.128-0.062,0.383,0.189,0.445,0.254c0.127,0.317,0.19,0.57,0.19,0.57l13.083,36.965 l33.344-37.6h14.1h3.365c9.337,0,15.055,3.747,13.528,10.354c-1.778,7.24-9.972,10.416-18.608,10.416h-3.238l4.191-17.783h-14.481 l-6.159,25.976h20.576c15.434,0,30.232-8.13,32.709-18.608C152.449,8.193,141.523,0.063,126.027,0.063L126.027,0.063z M71.091,45.981c-39.123,0-70.816,4.512-70.816,10.035c0,5.59,31.693,10.034,70.816,10.034c39.121,0,70.877-4.444,70.877-10.034 C141.968,50.493,110.212,45.981,71.091,45.981L71.091,45.981z M68.55,59.573c-8.956,0-16.196-1.523-16.196-3.365 c0-1.84,7.239-3.303,16.196-3.303c8.955,0,16.195,1.463,16.195,3.303C84.745,58.05,77.505,59.573,68.55,59.573L68.55,59.573z" />
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
|
|
<body id="page-top" class="bg-animated">
|
|
|
|
<div class="d-block px-2 py-2 text-center text-bold bg-danger">
|
|
<a href="https://github.com/whosmatt/uvmod#statement-regarding-dangerous-clones-of-uvmod"
|
|
class="text-white">Warning: There are unauthorized clones of UVMOD, designed with no regards for safety. Check the
|
|
original repository for approved links! Click to learn more.</a>
|
|
</div>
|
|
|
|
<!-- Page Wrapper -->
|
|
<div id="wrapper animated--grow-in" class="wrapper">
|
|
|
|
<!-- Sidebar -->
|
|
<div id="navbar-placeholder" class="sidebar toggled"></div>
|
|
<script src="js/navbar.js"></script>
|
|
|
|
<!-- Content Wrapper -->
|
|
<div id="content-wrapper" class="w-100">
|
|
|
|
<!-- Main Content -->
|
|
<div id="content" class="fade-in-from-bottom">
|
|
|
|
<!-- Begin Page Content -->
|
|
<div class="container mt-4" style="max-width: 1440px;">
|
|
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<div class="card shadow mb-4">
|
|
<a href="#instructions" class="d-block card-header py-3" data-toggle="collapse" role="button">
|
|
<h6 class="m-0 font-weight-bold text-primary">Instructions</h6>
|
|
</a>
|
|
<div id="instructions" class="card-body collapse">
|
|
<h2 class="mb-4">UVMOD Configurator</h2>
|
|
<p>This tool lets you edit the settings and channels of your radio from the comfort of your web
|
|
browser. It serves as a platform independent replacement for the official CPS software. </p>
|
|
|
|
<h3 class="mt-4">Usage</h3>
|
|
<p>The configurator is currently under development. Right now it can only read the configuration of
|
|
the radio and save it as a backup. The backup *should* be compatible with k5prog but as of now it is
|
|
untested, so please avoid writing this backup to any radio just yet. </p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content Row -->
|
|
<div class="row">
|
|
|
|
<div class="col mb-4">
|
|
<!-- Mods -->
|
|
<div class="card shadow-lg mb-4">
|
|
<div class="card-header py-3 d-flex">
|
|
<div class="mr-auto">
|
|
<h6 class="m-0 font-weight-bold text-primary">Configuration</h6>
|
|
</div>
|
|
</div>
|
|
<div id="modsContainer" class="card-body">
|
|
<p class="text-center mb-0">Please read config or load a backup.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-5 mb-4">
|
|
<!-- Console -->
|
|
<div class="card shadow mb-4 sticky-top" style="top: 1.5rem">
|
|
<div class="card-header py-3 d-flex">
|
|
<div class="mr-auto">
|
|
<h6 class="m-0 font-weight-bold text-primary">Console</h6>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="d-flex justify-content-center">
|
|
<textarea id="console" class="w-100 form-control" style="height: 10em;" readonly></textarea>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="input-group mt-4">
|
|
<div class="input-group-prepend">
|
|
<div class="input-group-text">
|
|
<input id="automaticBackupCheckbox" style="cursor: pointer;" type="checkbox" checked>
|
|
</div>
|
|
</div>
|
|
<label for="automaticBackupCheckbox" class="form-control" readonly style="cursor: pointer;">Save
|
|
automatic backup</label>
|
|
</div>
|
|
</div>
|
|
<div class="custom-file mt-2">
|
|
<input id="backupFileInput" type="file" class="custom-file-input" accept=".bin" style="cursor: pointer;">
|
|
<label id="backupFileLabel" class="custom-file-label" for="backupFileInput" data-default-text="Import backup file">Import backup file</label>
|
|
</div>
|
|
|
|
<div class="mt-2 d-flex">
|
|
<a id="readConfigButton" class="btn btn-dark btn-icon-split mr-1 w-100">
|
|
<span class="icon text-white-50">
|
|
<i class="fas fa-sign-out-alt"></i>
|
|
</span>
|
|
<span class="text w-100">Read Config</span>
|
|
</a>
|
|
<a id="writeConfigButton" class="btn btn-dark btn-icon-split disabled w-100">
|
|
<span class="icon text-white-50">
|
|
<i class="fas fa-sign-in-alt"></i>
|
|
</span>
|
|
<span class="text w-100">Write Config</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<!-- /.container-fluid -->
|
|
|
|
</div>
|
|
<!-- End of Main Content -->
|
|
|
|
</div>
|
|
<!-- End of Content Wrapper -->
|
|
|
|
</div>
|
|
<!-- End of Page Wrapper -->
|
|
|
|
<!-- Bootstrap core JavaScript-->
|
|
<script src="js/vendor/jquery.min.js"></script>
|
|
<script src="js/vendor/bootstrap.bundle.min.js"></script>
|
|
<script src="js/vendor/bs-custom-file-input.min.js"></script>
|
|
|
|
<!-- Core plugin JavaScript-->
|
|
|
|
<!-- Configurator JavaScript -->
|
|
<script src="js/fwpack.js"></script>
|
|
<script src="js/qsSerial.js"></script>
|
|
<script src="js/modframework.js"></script>
|
|
<script src="js/configurators.js"></script>
|
|
<script src="js/tool_configurator.js"></script>
|
|
|
|
<!-- Translation JavaScript -->
|
|
<script src="https://cdn.jsdelivr.net/npm/i18next@23.5.1/i18next.min.js"></script>
|
|
<script
|
|
src="https://cdn.jsdelivr.net/npm/i18next-browser-languagedetector@7.1.0/i18nextBrowserLanguageDetector.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/i18next-http-backend@2.2.2/i18nextHttpBackend.min.js"></script>
|
|
<script src="js/i18n.js"></script>
|
|
<script>
|
|
i18next.on("initialized", function (options) {
|
|
//init();
|
|
});
|
|
</script>
|
|
|
|
<!-- Easter egg, click the title -->
|
|
<script>
|
|
const marqueediv = document.getElementById("marquee");
|
|
|
|
(function ($, window, undefined) {
|
|
$.fn.marqueeify = function (options) {
|
|
var settings = $.extend({
|
|
horizontal: true,
|
|
vertical: true,
|
|
speed: 100, // In pixels per second
|
|
container: $(this).parent(),
|
|
bumpEdge: function () { }
|
|
}, options);
|
|
|
|
return this.each(function () {
|
|
var containerWidth, containerHeight, elWidth, elHeight, move, getSizes,
|
|
$el = $(this);
|
|
|
|
getSizes = function () {
|
|
containerWidth = settings.container.outerWidth();
|
|
containerHeight = settings.container.outerHeight();
|
|
elWidth = $el.outerWidth();
|
|
elHeight = $el.outerHeight();
|
|
};
|
|
|
|
move = {
|
|
right: function () {
|
|
$el.animate({ left: (containerWidth - elWidth) }, {
|
|
duration: ((containerWidth / settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
|
settings.bumpEdge();
|
|
move.left();
|
|
}
|
|
});
|
|
},
|
|
left: function () {
|
|
$el.animate({ left: 0 }, {
|
|
duration: ((containerWidth / settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
|
settings.bumpEdge();
|
|
move.right();
|
|
}
|
|
});
|
|
},
|
|
down: function () {
|
|
$el.animate({ top: (containerHeight - elHeight) }, {
|
|
duration: ((containerHeight / settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
|
settings.bumpEdge();
|
|
move.up();
|
|
}
|
|
});
|
|
},
|
|
up: function () {
|
|
$el.animate({ top: 0 }, {
|
|
duration: ((containerHeight / settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
|
settings.bumpEdge();
|
|
move.down();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
getSizes();
|
|
if (settings.horizontal) {
|
|
move.right();
|
|
}
|
|
if (settings.vertical) {
|
|
move.down();
|
|
}
|
|
|
|
// Make that shit responsive!
|
|
$(window).resize(function () {
|
|
getSizes();
|
|
});
|
|
});
|
|
};
|
|
})(jQuery, window);
|
|
|
|
var marqueeified = false;
|
|
function easterEgg() {
|
|
$('.marquee').toggle();
|
|
if (!marqueeified) {
|
|
$('.marquee').marqueeify({
|
|
speed: 150,
|
|
bumpEdge: function () {
|
|
var newColor = "hsl(" + Math.floor(Math.random() * 360) + ", 100%, 50%)";
|
|
$('.marquee .logo').css('fill', newColor);
|
|
}
|
|
});
|
|
marqueeified = true;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
</html> |