Finished settings page

This commit is contained in:
Leon Etienne (ubuntu wsl) 2020-10-02 18:09:51 +02:00
parent 5f7e4e2cf2
commit cb5f43bf25
53 changed files with 430 additions and 63 deletions

View File

@ -90,7 +90,8 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
peer_addr = buf;
}
if (IsConnectionAllowed(peer_addr))
std::string denialReason;
if (IsConnectionAllowed(peer_addr, denialReason))
{
try
{
@ -126,7 +127,7 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
else // Client is not allowed, serve error json
{
Json j;
j.CloneFrom(RestResponseTemplates::GetByCode(UNAUTHORIZED, "Only localhost allowed!"));
j.CloneFrom(RestResponseTemplates::GetByCode(UNAUTHORIZED, denialReason));
ServeStringToConnection(pNc, j.Render(), UNAUTHORIZED);
}
}
@ -200,13 +201,17 @@ void HttpServer::ServeDownloadeableResource(mg_connection* pNc, int ev, void* p,
return;
}
bool HttpServer::IsConnectionAllowed(std::string peer_address)
bool HttpServer::IsConnectionAllowed(std::string peer_address, std::string& denialReason)
{
// Localhost is always allowed!
if (peer_address == "127.0.0.1") return true;
// Peer is not localhost, but only localhost is allowed!
else if (XGConfig::access.only_allow_localhost) return false;
else if (XGConfig::access.only_allow_localhost)
{
denialReason = "Only localhost allowed!";
return false;
}
// Let's check if the whitelist is active
else if (XGConfig::access.enable_whitelist)
@ -219,6 +224,7 @@ bool HttpServer::IsConnectionAllowed(std::string peer_address)
}
// Whitelist is enabled, but peer is NOT whitelisted
denialReason = "Not whitelisted!";
return false;
}
else // Whitelist is NOT enabled and only_allow_localhost is FALSE!
@ -227,6 +233,7 @@ bool HttpServer::IsConnectionAllowed(std::string peer_address)
}
// Should never come to this point
denialReason = "Access denied";
return false;
}

View File

@ -29,7 +29,7 @@ namespace Rest
static void ServeStringToConnection(struct mg_connection* c, std::string str, int httpStatusCode = 200);
static std::string FixUnterminatedString(const char* cstr, const std::size_t len);
static bool IsConnectionAllowed(std::string peer_address);
static bool IsConnectionAllowed(std::string peer_address, std::string& denialReason);
struct mg_mgr* pMgr;

View File

@ -43,6 +43,7 @@ bool RestQueryHandler::ProcessQuery(const std::string clientAdress, const Json&
else if (requestName == "update_dep_youtubedl") return UpdateYoutubeDL(requestBody, responseBody, responseCode);
else if (requestName == "remove_download_entry") return RemoveDownloadEntry(requestBody, responseBody, responseCode);
else if (requestName == "update_config") return UpdateConfig(requestBody, responseBody, responseCode);
else if (requestName == "reset_config_to_default_values") return ResetConfigDefaults(requestBody, responseBody, responseCode);
@ -440,7 +441,11 @@ bool RestQueryHandler::RemoveDownloadEntry(const JsonBlock& request, JsonBlock&
bool RestQueryHandler::UpdateConfig(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
{
if (ValidateField("config", JDType::JSON, request, responseBody))
responseCode = OK;
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
JsonBlock dummy;
if (ValidateField("config", JDType::JSON, request, dummy))
{
bool prevStateConsole = XGConfig::general.show_console;
XGConfig::LoadFromJson(request.Get("config").AsJson);
@ -456,19 +461,38 @@ bool RestQueryHandler::UpdateConfig(const JsonBlock& request, JsonBlock& respons
log->Flush();
XGConfig::Save();
responseBody.Set("message") = "Updated no settings";
responseBody.Set("message") = "Updated settings";
}
else
{
responseBody.Set("message") = "Updated no settings";
}
responseCode = OK;
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
responseBody.Set("settings") = XGConfig::GetSavefileBuffer();
responseBody.Set("config") = XGConfig::GetSavefileBuffer();
return true;
}
bool RestQueryHandler::ResetConfigDefaults(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
{
log->cout << "Reset config values to default...";
log->Flush();
bool prevStateConsole = XGConfig::general.show_console;
XGConfig::LoadDefaultValues();
XGConfig::Save();
// Update console, if necessary
if (XGConfig::general.show_console != prevStateConsole)
{
if (XGConfig::general.show_console) ConsoleManager::ShowConsole();
else ConsoleManager::HideConsole();
}
responseCode = OK;
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
responseBody.Set("message") = "Reset config to default...";
responseBody.Set("config") = XGConfig::GetSavefileBuffer();
return true;
}

View File

@ -35,6 +35,7 @@ namespace Rest
static bool UpdateYoutubeDL(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool RemoveDownloadEntry(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool UpdateConfig(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool ResetConfigDefaults(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool ValidateField(const std::string name, const JasonPP::JDType type, const JasonPP::Json& checkThat, JasonPP::JsonBlock& putErrorResponseHere);

View File

@ -6,7 +6,7 @@ void XGConfig::PreInit()
{
log = new ::Logging::Logger("Config");
InitializeDefaultValues();
LoadDefaultValues();
if (FileSystem::Exists(XGCONFIG_FILE))
{
@ -30,7 +30,7 @@ bool XGConfig::IsJsonFieldValid(const JsonBlock& json, const std::string key, co
return ((json.DoesShorthandExist(key)) && (json.ShorthandGet(key).GetDataType() == type));
}
void XGConfig::InitializeDefaultValues()
void XGConfig::LoadDefaultValues()
{
httpServer.port = "6969";
httpServer.polling_rate = 100;
@ -46,11 +46,14 @@ void XGConfig::InitializeDefaultValues()
general.show_console = true;
access.only_allow_localhost = true;
access.enable_whitelist = true;
access.only_allow_localhost = false;
access.enable_whitelist = false;
access.whitelist = std::vector<std::string>();
access.whitelist.push_back("127.0.0.1"); // Add localhost to whitelist
savefileBuffer.Clear();
savefileBuffer.CloneFrom(CreateJson());
return;
}

View File

@ -44,6 +44,7 @@ public:
static void PostExit();
static void LoadFromJson(const JasonPP::JsonBlock& json);
static void LoadDefaultValues();
static XGConfig::HttpServer httpServer;
static XGConfig::Logging logging;
@ -60,7 +61,6 @@ private:
static JasonPP::JsonBlock savefileBuffer;
static bool IsJsonFieldValid(const JasonPP::JsonBlock& json, const std::string key, const JasonPP::JDType type);
static void InitializeDefaultValues();
static JasonPP::JsonBlock CreateJson();
static void Load();
};

View File

@ -1,9 +1,9 @@
<!doctype html>
<html>
<head>
<title>Tubio - Video downloader</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content=""><link data-n-head="1" rel="icon" type="image/x-icon" href="/favicon.ico"><link rel="preload" href="/_nuxt/39f2f1c.js" as="script"><link rel="preload" href="/_nuxt/b2cccba.js" as="script"><link rel="preload" href="/_nuxt/d0a20ff.js" as="script"><link rel="preload" href="/_nuxt/ffabd53.js" as="script">
<title>Tubio - Video downloader</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content=""><meta data-n-head="1" name="msapplication-TileColor" content="#031934"><meta data-n-head="1" name="theme-color" content="#031934"><link data-n-head="1" rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link data-n-head="1" rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link data-n-head="1" rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link data-n-head="1" rel="manifest" href="/site.webmanifest"><link data-n-head="1" rel="mask-icon" href="/safari-pinned-tab.svg" color="#031934"><link rel="preload" href="/_nuxt/b0ecca0.js" as="script"><link rel="preload" href="/_nuxt/2b1a86c.js" as="script"><link rel="preload" href="/_nuxt/d429197.js" as="script"><link rel="preload" href="/_nuxt/7e93adc.js" as="script">
</head>
<body>
<div id="__nuxt"><style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style><script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script><div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div></div><script>window.__NUXT__={config:{},staticAssetsBase:"/_nuxt/static/1601497777"}</script>
<script src="/_nuxt/39f2f1c.js"></script><script src="/_nuxt/b2cccba.js"></script><script src="/_nuxt/d0a20ff.js"></script><script src="/_nuxt/ffabd53.js"></script></body>
<div id="__nuxt"><style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style><script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script><div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div></div><script>window.__NUXT__={config:{},staticAssetsBase:"/_nuxt/static/1601654949"}</script>
<script src="/_nuxt/b0ecca0.js"></script><script src="/_nuxt/2b1a86c.js"></script><script src="/_nuxt/d429197.js"></script><script src="/_nuxt/7e93adc.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
!function(e){function r(data){for(var r,n,f=data[0],l=data[1],d=data[2],i=0,h=[];i<f.length;i++)n=f[i],Object.prototype.hasOwnProperty.call(o,n)&&o[n]&&h.push(o[n][0]),o[n]=0;for(r in l)Object.prototype.hasOwnProperty.call(l,r)&&(e[r]=l[r]);for(v&&v(data);h.length;)h.shift()();return c.push.apply(c,d||[]),t()}function t(){for(var e,i=0;i<c.length;i++){for(var r=c[i],t=!0,n=1;n<r.length;n++){var l=r[n];0!==o[l]&&(t=!1)}t&&(c.splice(i--,1),e=f(f.s=r[0]))}return e}var n={},o={4:0},c=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var c,script=document.createElement("script");script.charset="utf-8",script.timeout=120,f.nc&&script.setAttribute("nonce",f.nc),script.src=function(e){return f.p+""+{2:"8f02b2f",3:"56889ef"}[e]+".js"}(e);var l=new Error;c=function(r){script.onerror=script.onload=null,clearTimeout(d);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),c=r&&r.target&&r.target.src;l.message="Loading chunk "+e+" failed.\n("+n+": "+c+")",l.name="ChunkLoadError",l.type=n,l.request=c,t[1](l)}o[e]=void 0}};var d=setTimeout((function(){c({type:"timeout",target:script})}),12e4);script.onerror=script.onload=c,document.head.appendChild(script)}return Promise.all(r)},f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(object,e){return Object.prototype.hasOwnProperty.call(object,e)},f.p="/_nuxt/",f.oe=function(e){throw console.error(e),e};var l=window.webpackJsonp=window.webpackJsonp||[],d=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var v=d;t()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){function r(data){for(var r,n,l=data[0],f=data[1],d=data[2],i=0,h=[];i<l.length;i++)n=l[i],Object.prototype.hasOwnProperty.call(o,n)&&o[n]&&h.push(o[n][0]),o[n]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);for(v&&v(data);h.length;)h.shift()();return c.push.apply(c,d||[]),t()}function t(){for(var e,i=0;i<c.length;i++){for(var r=c[i],t=!0,n=1;n<r.length;n++){var f=r[n];0!==o[f]&&(t=!1)}t&&(c.splice(i--,1),e=l(l.s=r[0]))}return e}var n={},o={4:0},c=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var c,script=document.createElement("script");script.charset="utf-8",script.timeout=120,l.nc&&script.setAttribute("nonce",l.nc),script.src=function(e){return l.p+""+{2:"d4b440d",3:"d7b3322"}[e]+".js"}(e);var f=new Error;c=function(r){script.onerror=script.onload=null,clearTimeout(d);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),c=r&&r.target&&r.target.src;f.message="Loading chunk "+e+" failed.\n("+n+": "+c+")",f.name="ChunkLoadError",f.type=n,f.request=c,t[1](f)}o[e]=void 0}};var d=setTimeout((function(){c({type:"timeout",target:script})}),12e4);script.onerror=script.onload=c,document.head.appendChild(script)}return Promise.all(r)},l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(object,e){return Object.prototype.hasOwnProperty.call(object,e)},l.p="/_nuxt/",l.oe=function(e){throw console.error(e),e};var f=window.webpackJsonp=window.webpackJsonp||[],d=f.push.bind(f);f.push=r,f=f.slice();for(var i=0;i<f.length;i++)r(f[i]);var v=d;t()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
window.__NUXT__={staticAssetsBase:"\u002F_nuxt\u002Fstatic\u002F1601654949",layout:"default",error:null,state:{diskUsage:{usage:{}},dlcache:{cache:[]},logs:{logs:[]},serverOs:{os_name:""},settings:{config:{}}},serverRendered:true,routePath:"\u002Fsettings",config:{}};

View File

@ -0,0 +1 @@
window.__NUXT__={staticAssetsBase:"\u002F_nuxt\u002Fstatic\u002F1601654949",layout:"default",error:null,state:{diskUsage:{usage:{}},dlcache:{cache:[]},logs:{logs:[]},serverOs:{os_name:""},settings:{config:{}}},serverRendered:true,routePath:"\u002F",config:{}};

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="595.000000pt" height="595.000000pt" viewBox="0 0 595.000000 595.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,595.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 2975 l0 -2415 2975 0 2975 0 0 2415 0 2415 -2975 0 -2975 0 0
-2415z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 603 B

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@ -30,9 +30,9 @@ export default {
mounted() {
const that = this;
this.$store.dispatch("dlcache/update", this);
this.$store.dispatch("dlcache/update");
setInterval(function(){
that.$store.dispatch("dlcache/update", that);
that.$store.dispatch("dlcache/update");
}, 1000);
return;
}

View File

@ -23,9 +23,9 @@ export default {
mounted() {
const that = this;
this.$store.dispatch("logs/update", this);
this.$store.dispatch("logs/update");
setInterval(function(){
that.$store.dispatch("logs/update", that);
that.$store.dispatch("logs/update");
}, 1000);
return;
}

View File

@ -16,10 +16,16 @@ export default {
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
{ hid: 'description', name: 'description', content: '' },
{ name: 'msapplication-TileColor', content: '#031934' },
{ name: 'theme-color', content: '#031934' },
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
{ rel: 'apple-touch-icon', sizes: "180x180", href: '/apple-touch-icon.png' },
{ rel: 'icon', type: "image/png", sizes: "32x32", href: '/favicon-32x32.png' },
{ rel: 'icon', type: "image/png", sizes: "16x16", href: '/favicon-16x16.png' },
{ rel: 'manifest', href: '/site.webmanifest' },
{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#031934' },
]
},

View File

@ -2,13 +2,20 @@
<div>
<div class="hidden md:block">
<Spacer height="0.5em" m_height="1em" />
<Spacer height="0" m_height="1em" />
<Logo class="logo mt-4" />
<Spacer height="2em" m_height="2em" />
</div>
<div class="flex flex-row flex-wrap md:flex-no-wrap input-flex justify-between md:justify-center">
<input class="flex-grow md:mr-4 mb-2 md:mb-0 w-full" type="url" name="video_url" id="video_url" ref="video_url" placeholder="video-url">
<input class="flex-grow md:mr-4 mb-2 md:mb-0 w-full"
type="url"
name="video_url"
id="video_url"
ref="video_url"
placeholder="video-url"
v-on:keydown="keyMonitor"
/>
<div class="w-full md:hidden" />
@ -47,7 +54,7 @@ export default {
},
methods: {
downloadButtonClicked: function(){
downloadButtonClicked: function() {
const that = this;
if (this.$refs.video_url.value.match(/(https?:\/\/)?[a-zA-Z0-9-_.]+\.[a-zA-Z-_.]+/)) {
@ -63,7 +70,13 @@ export default {
}
});
}
return;
},
keyMonitor: function(event) {
if (event.key == "Enter") {
this.downloadButtonClicked();
}
return;
}
}

View File

@ -9,24 +9,68 @@
<div class="w-full lg:w-1/2 border-right lg:pr-3">
<div v-if="typeof(getSettings().general) != 'undefined'">
<div v-if="serverOs === 'Windows'" class="option toggle flex justify-between items-center">
<p>Show console</p>
<Toggle :isOn="false"/>
<div v-on:click="setSettings_toggle_showConsole">
<Toggle
:isOn="getSettings().general.show_console"
/>
</div>
</div>
<div class="option text narrow flex justify-between w-full items-center">
<p class="mr-3">Max speed</p>
<input type="text" id="max_speed" name="max_speed" placeholder="100M">
<input
type="text"
id="max_speed"
name="max_speed"
placeholder="100M"
v-model="getSettings().downloader.max_dlrate_per_thread"
v-on:focusout="setSettings_pushCurrentStore"
/>
</div>
<div class="option text narrow flex justify-between w-full items-center">
<p class="mr-3">Download threads</p>
<input type="text" id="max_threads" name="max_threads" placeholder="10">
<input
type="number"
id="max_threads"
name="max_threads"
placeholder="10"
v-model.number="getSettings().downloader.num_threads"
v-on:focusout="setSettings_pushCurrentStore"
/>
</div>
<div class="option toggle flex justify-between items-center">
<p>Only allow localhost</p>
<div v-on:click="setSettings_toggle_onlyAllowLocalhost">
<Toggle
:isOn="getSettings().access.only_allow_localhost"
/>
</div>
</div>
<div class="option toggle flex justify-between items-center">
<p>Enable whitelist</p>
<Toggle :isOn="false"/>
<div v-on:click="setSettings_toggle_enableWhitelist">
<Toggle
:isOn="getSettings().access.enable_whitelist"
/>
</div>
</div>
<Spacer height="2em" />
<div v-if="getSettings().access.enable_whitelist">
<h2>Whitelist</h2>
<textarea class="mt-2 w-full" ref="whitelist_input" v-on:input="whitelistInputJsonSyntaxCheck" />
<div class="flex w-full">
<div class="button button--small button--nowarn mt-2 mr-2" v-on:click="saveWhitelist" ref="button_saveWhitelist">Save whitelist</div>
<div class="button button--small button--nowarn mt-2" v-on:click="updateWhitelist">Update whitelist</div>
</div>
</div>
</div>
</div>
@ -68,6 +112,7 @@
</div>
<div class="flex flex-col ml-1">
<div class="button" v-on:click="killServer">Kill server</div>
<div class="button mt-2" v-on:click="resetToDefaults">Reset to defaults</div>
</div>
</div>
@ -112,7 +157,7 @@ export default {
},
serverOs: function() {
return this.$store.state.serverOs.os_name;
}
},
},
methods: {
@ -163,11 +208,112 @@ export default {
});
return;
},
resetToDefaults: function() {
this.$store.dispatch("settings/resetToDefaults");
},
getSettings: function() {
return this.$store.state.settings.config;
},
setSettings_toggle_showConsole: function() {
var curConf = this.getSettings();
curConf.general.show_console = !curConf.general.show_console;
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
return;
},
setSettings_toggle_onlyAllowLocalhost: function() {
var curConf = this.getSettings();
curConf.access.only_allow_localhost = !curConf.access.only_allow_localhost;
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
return;
},
setSettings_toggle_enableWhitelist: function() {
var curConf = this.getSettings();
curConf.access.enable_whitelist = !curConf.access.enable_whitelist;
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
if (curConf.access.enable_whitelist) {
this.whitelistToInputfield();
}
return;
},
setSettings_pushCurrentStore: function() {
this.$store.dispatch("settings/updateSet", this.getSettings());
return;
},
whitelistToInputfield: function() {
// If this.$refs.whitelist_input is still undefined, just try again later, lmao
if (typeof(this.$refs.whitelist_input) === "undefined") {
setTimeout(this.whitelistToInputfield, 200);
}
else {
var whitelistString = JSON.stringify(this.getSettings().access.whitelist, undefined, 2);
this.$refs.whitelist_input.value = whitelistString;
return whitelistString;
}
},
saveWhitelist: function() {
const prevContent = this.$refs.whitelist_input.value;
const element = this.$refs.whitelist_input;
try {
const arrayWhitelist = JSON.parse(prevContent);
var curConf = this.getSettings();
curConf.access.whitelist = arrayWhitelist;
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
this.whitelistToInputfield();
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
element.classList.remove("inputfield--error");
} catch (e) {
this.$refs.whitelist_input.value = prevContent;
element.classList.add("inputfield--error");
this.$refs.button_saveWhitelist.classList.add("button--disabled");
}
return;
},
updateWhitelist: function() {
const that = this;
this.$store.dispatch("settings/updateGet", function() {
that.whitelistToInputfield();
that.whitelistInputJsonSyntaxCheck();
return;
});
return;
},
whitelistInputJsonSyntaxCheck: function() {
const element = this.$refs.whitelist_input;
try {
JSON.parse(element.value);
element.classList.remove("inputfield--error");
this.$refs.button_saveWhitelist.classList.remove("button--disabled");
} catch (e) {
element.classList.add("inputfield--error");
this.$refs.button_saveWhitelist.classList.add("button--disabled");
}
return;
}
},
mounted() {
this.$store.dispatch("diskUsage/update", this);
this.$store.dispatch("serverOs/update", this);
const that = this;
this.$store.dispatch("diskUsage/update");
this.$store.dispatch("serverOs/update");
this.$store.dispatch("settings/updateGet", function() {
that.whitelistToInputfield();
});
setInterval(function(){
that.$store.dispatch("settings/updateGet");
}, 1000);
return;
}
};
@ -197,6 +343,19 @@ h2 {
}
}
textarea {
color: theme("colors.purple-0");
border-radius: 5px;
font-size: 16pt;
padding: 0.7em;
min-height: 200px;
transition: background-color 0.2s;
&.inputfield--error {
background-color: #f77;
}
}
.option {
color: theme("colors.text-gray-1");
font-size: 18pt;
@ -239,12 +398,30 @@ h2 {
color: #000;
font-family: ZillaSlab, serif;
font-size: 18pt;
transition: background-color 0.2s;
width: 200px;
transition:
background-color 0.2s,
opacity 0.2s;
&:hover {
background-color: theme("colors.text-error-1");
}
&--small {
font-size: 14pt;
width: 150px;
height: 30px;
}
&--nowarn:hover {
background-color: theme("colors.purple-1");
}
&--disabled {
cursor: pointer;
pointer-events: none;
opacity: 0.5;
}
}
hr {

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="595.000000pt" height="595.000000pt" viewBox="0 0 595.000000 595.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,595.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 2975 l0 -2415 2975 0 2975 0 0 2415 0 2415 -2975 0 -2975 0 0
-2415z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 603 B

View File

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@ -11,13 +11,13 @@ export const mutations = {
};
export const actions = {
update(context, instance) {
update(context) {
axios.post("/api", {
request: "get_disk_usage"
})
.then(function(response) {
if (response.data.status === "OK") {
instance.$store.commit("diskUsage/update", response.data.disk_usage);
context.commit("update", response.data.disk_usage);
}
});
},

View File

@ -11,13 +11,13 @@ export const mutations = {
};
export const actions = {
update(context, instance) {
update(context) {
axios.post("/api", {
request: "fetch_alltime_cache"
})
.then(function(response) {
if (response.data.status === "OK") {
instance.$store.commit("dlcache/update", response.data.cache);
context.commit("update", response.data.cache);
}
});
},

View File

@ -11,13 +11,13 @@ export const mutations = {
};
export const actions = {
update(context, instance) {
update(context) {
axios.post("/api", {
request: "fetch_session_logs"
})
.then(function(response) {
if (response.data.status === "OK") {
instance.$store.commit("logs/update", response.data.logs);
context.commit("update", response.data.logs);
}
});
},

View File

@ -11,13 +11,13 @@ export const mutations = {
};
export const actions = {
update(context, instance) {
update(context) {
axios.post("/api", {
request: "get_os_name"
})
.then(function(response) {
if (response.data.status === "OK") {
instance.$store.commit("serverOs/update", response.data.os_name);
context.commit("update", response.data.os_name);
}
});
},

View File

@ -0,0 +1,48 @@
import axios from 'axios';
export const state = () => ({
config: {}
});
export const mutations = {
updateGet(state, data) {
state.config = data;
},
};
export const actions = {
updateGet(context, callback) {
axios.post("/api", {
request: "update_config"
})
.then(function(response) {
if (response.data.status === "OK") {
context.commit("updateGet", response.data.config);
if (typeof(callback) === "function") callback();
}
});
},
updateSet(context, newConfig) {
axios.post("/api", {
request: "update_config",
config: newConfig
})
.then(function(response) {
if (response.data.status === "OK") {
// Also update the vuex store...
context.commit("updateGet", response.data.config);
}
});
},
resetToDefaults(context) {
axios.post("/api", {
request: "reset_config_to_default_values"
})
.then(function(response) {
if (response.data.status === "OK") {
// Also update the vuex store...
context.commit("updateGet", response.data.config);
}
});
}
};