mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
897 lines
28 KiB
HTML
897 lines
28 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />
|
|
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
|
|
<!--<link href="./dependencies/vuetify.min.css" rel="stylesheet">-->
|
|
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.7.1/dist/vuetify.min.css" rel="stylesheet">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
|
|
|
|
<style>
|
|
html {
|
|
overflow: hidden;
|
|
}
|
|
#topMenu {
|
|
width: 100%;
|
|
height: 70px;
|
|
background-color: black;
|
|
}
|
|
.menuTab {
|
|
display: inline-block;
|
|
height: 100%;
|
|
padding-left: 20px;
|
|
padding-right: 20px;
|
|
vertical-align: top;
|
|
line-height: 70px;
|
|
color: #AAAAAA;
|
|
cursor: pointer;
|
|
}
|
|
.menuTab.active {
|
|
background-color: #140a4a;
|
|
color: white;
|
|
}
|
|
|
|
#mainContainer {
|
|
|
|
}
|
|
#mainContainer .page {
|
|
position: absolute;
|
|
top: 70px;
|
|
left: 0px;
|
|
width: 100%;
|
|
height: calc(100% - 70px);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.requestCard {
|
|
margin: 10px;
|
|
}
|
|
.requestCard .title {
|
|
margin-left: 10px;
|
|
}
|
|
.requestCard .description {
|
|
font-weight: lighter;
|
|
margin-left: 10px;
|
|
}
|
|
.requestCard .code {
|
|
font-weight: lighter;
|
|
margin-left: 10px;
|
|
background-color: rgba(0,0,0,.3);
|
|
font-family: consolas;
|
|
padding: 10px;
|
|
}
|
|
|
|
.requestCard .parameter {
|
|
position: relative;
|
|
width: 100%;
|
|
padding: 5px;
|
|
margin-bottom: 10px;
|
|
border-radius: 20px;
|
|
margin: 5px;
|
|
}
|
|
.requestCard .parameter .name {
|
|
position: absolute;
|
|
width: 100px;
|
|
margin-left: 10px;
|
|
text-align: right;
|
|
padding: 10px;
|
|
top: 0px;
|
|
left: 0px;
|
|
}
|
|
.requestCard .parameter .description {
|
|
top: 0px;
|
|
padding: 5px;
|
|
font-weight: lighter;
|
|
margin-left: 120px;
|
|
}
|
|
.requestCard .parameter input {
|
|
margin: 10px;
|
|
background-color: #444444;
|
|
margin-left: 120px;
|
|
color: white;
|
|
padding: 5px;
|
|
width: calc(100% - 140px);
|
|
}
|
|
|
|
.testResult {
|
|
height: calc(100% - 125px);
|
|
overflow-y: auto;
|
|
white-space: pre-wrap;
|
|
background-color: #222222;
|
|
padding: 10px;
|
|
font-family: consolas, "Courier New";
|
|
font-size: 10px;
|
|
}
|
|
.testResult.exception {
|
|
color: red;
|
|
}
|
|
|
|
.property {
|
|
font-weight: 300;
|
|
margin-bottom: 15px;
|
|
}
|
|
.property .key {
|
|
color: white;
|
|
}
|
|
.property .value {
|
|
color: #999999;
|
|
}
|
|
|
|
.logContainer {
|
|
background-color: rgba(0,0,0,.5);
|
|
border-radius: 30px;
|
|
height: 500px;
|
|
font-family: consolas;
|
|
font-size: 16px;
|
|
padding: 30px;
|
|
overflow-y: auto;
|
|
}
|
|
.logLine {
|
|
color: white;
|
|
}
|
|
.logLine.exception {
|
|
color: red;
|
|
}
|
|
.logLine.system {
|
|
color: blue;
|
|
}
|
|
.logType {
|
|
display: inline-block;
|
|
font-weight: lighter;
|
|
}
|
|
.logMsg {
|
|
display: inline-block;
|
|
font-weight: 300;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.pastPluginUrl {
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
width: 500px;
|
|
text-align: center;
|
|
margin-top: 10px;
|
|
margin-bottom: 10px;
|
|
padding: 10px;
|
|
background-color: #1e1e1e;
|
|
border-radius: 50px;
|
|
box-shadow: 0px 1px 2px #131313;
|
|
font-weight: lighter;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<v-app>
|
|
<v-main>
|
|
<div id="topMenu">
|
|
<div style="height: 100%; display: inline-block; padding-left: 10px; padding-right: 20px;">
|
|
<img src="./dependencies/FutoMainLogo.svg"
|
|
style="margin-top: 20px;" />
|
|
</div>
|
|
<div class="menuTab" :class="{ 'active': page == 'Plugin' }" @click="page = 'Plugin'">
|
|
Overview
|
|
</div>
|
|
<div class="menuTab" :class="{ 'active': page == 'Testing' }" @click="page = 'Testing'">
|
|
Testing
|
|
</div>
|
|
<div class="menuTab" :class="{ 'active': page == 'Integration' }" @click="page = 'Integration'">
|
|
Integration
|
|
</div>
|
|
<div class="menuTab" :class="{ 'active': page == 'Settings' }" @click="page = 'Settings'">
|
|
Settings
|
|
</div>
|
|
<div style="right: 370px; top: 15px; position: absolute" v-if="Plugin?.currentPlugin?.authentication">
|
|
<v-btn @click="loginTestPlugin()" v-if="!Plugin.isLoggedIn">
|
|
Login
|
|
</v-btn>
|
|
<v-btn @click="logoutTestPlugin()" v-if="Plugin.isLoggedIn">
|
|
Logout
|
|
</v-btn>
|
|
</div>
|
|
<img v-if="Plugin.currentPlugin"
|
|
:src="Plugin.currentPluginIcon"
|
|
style="right: 300px; top: 10px; width: 50px; width: 50px; position: absolute;" />
|
|
<div v-if="Plugin.currentPlugin" style="position: absolute; right: 100px; top: 12px; width: 180px;">
|
|
<div>
|
|
{{Plugin.currentPlugin.name}}
|
|
</div>
|
|
<div>
|
|
Last updated: {{Plugin.lastLoadTime}}
|
|
</div>
|
|
</div>
|
|
<v-btn class="mx-2" fab dark color="#140a4a" style="position: absolute; right: 10px; top: 5px;"
|
|
@click="reloadPlugin()" v-if="Plugin.currentPluginUrl">
|
|
<v-icon dark>mdi-refresh</v-icon>
|
|
</v-btn>
|
|
</div>
|
|
<div id="mainContainer">
|
|
<div class="page" v-if="page == 'Plugin'">
|
|
<div v-if="!Plugin.currentPlugin && !Plugin.currentScript">
|
|
<div style="margin-left: auto; margin-right: auto; width: 750px; vertical-align: top; padding-left: 40px;">
|
|
<v-card style="width: 450px; margin-top: 80px; display: inline-block;">
|
|
<v-card-text>
|
|
<div>
|
|
<v-text-field label="Plugin Config Json Url"
|
|
v-model="Plugin.newPluginUrl"></v-text-field>
|
|
<div style="margin-top: -10px;">
|
|
<v-switch v-model="Plugin.loadUsingTag"
|
|
label="Load using script tag"></v-switch>
|
|
<div style="font-size: 11px; margin-top: -20px; color: #888888">
|
|
Loading via script tag might give issues reloading script, as it makes the script part of DOM, but does allow debugging via dev console.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn @click="loadPlugin(Plugin.newPluginUrl)">Load Plugin</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
<v-card style="width: 250px; margin-top: 80px; display: inline-block; vertical-align: top;">
|
|
<v-card-title>
|
|
Package Overrides
|
|
</v-card-title>
|
|
<v-card-text>
|
|
<div>
|
|
<div style="font-size: 12px; font-weight: lighter;">
|
|
Enabling a package override replaces the package with a browser implementation.
|
|
This generally improves speed, at the cost of test accuracy.
|
|
</div>
|
|
<div v-for="(value, name, index) in Plugin.packagesOverridden">
|
|
<v-switch v-model="Plugin.packagesOverridden[name]" :label="name" :change="saveOverrides()"></v-switch>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
</div>
|
|
|
|
|
|
<div v-if="pastPluginUrls" style="margin-top: 60px;">
|
|
<h2 style="font-weight: lighter; text-align: center;">Past Plugins</h2>
|
|
<div class="pastPluginUrl" v-for="pastPluginUrl in pastPluginUrls" @click="this.Plugin.newPluginUrl = pastPluginUrl; loadPlugin(pastPluginUrl)">
|
|
{{pastPluginUrl}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<v-card style="width: 500px; margin-left: auto; margin-right: auto; margin-top: 20px;"
|
|
v-if="Plugin.currentPluginError">
|
|
<v-card-text>
|
|
<div>
|
|
<h2 style="color: red">Errors in Plugin</h2>
|
|
{{Plugin.currentPluginError}}
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
<v-card style="width: 500px; margin-left: auto; margin-right: auto; margin-top: 20px;"
|
|
v-if="Plugin.currentPlugin && Plugin.currentScript">
|
|
<v-card-text>
|
|
<div>
|
|
<h2>Your plugin is loaded</h2>
|
|
You can now use testing methods available on the webapp. <br /> <br />
|
|
The information and warnings the user will see when installing the app can be viewed below.
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
<v-card style="width: 500px; margin-left: auto; margin-right: auto; margin-top: 20px;"
|
|
v-if="Plugin.currentPlugin && Plugin.currentScript">
|
|
<v-card-text>
|
|
<div>
|
|
<div style="height: 100px;">
|
|
<img :src="Plugin.currentPluginIcon"
|
|
style="width: 100px; position: absolute; top: 0px; left: 0px; margin: 10px;" />
|
|
<div style="position: absolute; right: 5px; top: 5px;">
|
|
Last updated: {{Plugin.lastLoadTime}}
|
|
</div>
|
|
<div style="width: calc(100% - 100px); height: 100px; position: absolute; top: 0px; right: 0px; padding-top: 40px; padding-left: 40px;">
|
|
<h2>{{Plugin.currentPlugin.name}}</h2>
|
|
<div>
|
|
<span>By </span>
|
|
<span v-if="!Plugin.currentPlugin.authorUrl">{{Plugin.currentPlugin.author}}</span>
|
|
<span v-if="Plugin.currentPlugin.authorUrl">
|
|
<a :href="Plugin.currentPlugin.authorUrl" style="text-decoration: none;">
|
|
{{Plugin.currentPlugin.author}}
|
|
</a>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div style="color: #999999">
|
|
{{Plugin.currentPlugin.description}}
|
|
</div>
|
|
<div style="margin-top: 30px;">
|
|
<div class="property">
|
|
<div class="key">
|
|
Version
|
|
</div>
|
|
<div class="value">
|
|
{{Plugin.currentPlugin.version}}
|
|
</div>
|
|
</div>
|
|
<div class="property">
|
|
<div class="key">
|
|
Repository URL
|
|
</div>
|
|
<div class="value">
|
|
<a :href="Plugin.currentPlugin.scriptUrl">
|
|
{{Plugin.currentPlugin.repositoryUrl}}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="property">
|
|
<div class="key">
|
|
Script URL
|
|
</div>
|
|
<div class="value">
|
|
<a :href="Plugin.currentPlugin.scriptUrl">
|
|
{{Plugin.currentPlugin.scriptUrl}}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<a href="/reference_autocomplete.js" download="ref.js" style="text-decoration: none; margin-right: 10px;">
|
|
<v-btn>Ref.js</v-btn>
|
|
</a>
|
|
<a href="/reference_plugin.d.ts" download="plugin.d.ts" style="text-decoration: none; margin-right: 10px;">
|
|
<v-btn>Plugin.d.ts</v-btn>
|
|
</a>
|
|
<v-btn @click="reloadPlugin()">Reload</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
<div v-if="Plugin.warnings && Plugin.warnings.length > 0">
|
|
<h2 style="text-align: center; margin-top: 40px;">Warnings</h2>
|
|
<div style="text-align: center; color: #999999; font-size: 14px;">
|
|
These are the warnings a user will see when they attempt to install this plugin
|
|
</div>
|
|
<v-card style="width: 500px; margin-left: auto; margin-right: auto; margin-top: 20px; min-height: 130px;"
|
|
v-for="warning in Plugin.warnings">
|
|
<v-card-text>
|
|
<div>
|
|
<div class="material-symbols-outlined"
|
|
style="width: 100px; margin: 10px; color: rgb(194, 83, 83); font-size: 100px; position: absolute; top: 10px; left: 10px;">
|
|
security
|
|
</div>
|
|
<div style="margin-left: 120px;">
|
|
<div style="font-size: 18px;">
|
|
{{warning.first}}
|
|
</div>
|
|
<div style="color: #C25353">
|
|
{{warning.second}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
</div>
|
|
</div>
|
|
<div class="page" v-if="page == 'Testing'">
|
|
<v-card style="margin-top: 20px; margin-bottom: 20px; margin-left: auto; margin-right: auto; width: 500px;" v-if="!Plugin.currentPlugin">
|
|
<v-card-title>
|
|
No Plugin Loaded
|
|
</v-card-title>
|
|
</v-card-header>
|
|
<v-card-text>
|
|
<div>
|
|
Load a plugin before doing testing.
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
<div style="width: 50%" v-if="Plugin.currentPlugin">
|
|
<!--Get Home-->
|
|
<v-card class="requestCard" v-for="req in Testing.requests">
|
|
<v-card-text>
|
|
<div class="title">
|
|
<span v-if="req.isOptional">(Optional)</span>
|
|
<span>{{req.title}}</span>
|
|
</div>
|
|
<!--
|
|
<div v-if="req.title == 'enable'" style="position: absolute; top:3px; right: 18px">
|
|
<v-checkbox v-model="Plugin.enableOnReload" label="Enable on Refresh" />
|
|
</div> -->
|
|
<div class="description">
|
|
{{req.description}}
|
|
</div>
|
|
<div class="code">
|
|
{{req.code}}
|
|
</div>
|
|
<div>
|
|
<div class="parameter" v-for="parameter in req.parameters">
|
|
<div class="name">
|
|
{{parameter.name}}
|
|
</div>
|
|
<div class="description">
|
|
{{parameter.description}}
|
|
</div>
|
|
<input type="text" :placeholder="parameter.name + ' value'" v-model="parameter.value" />
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn @click="testSource(req)">
|
|
Test
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</div>
|
|
<div style="position: fixed; right: 0px; top: 70px;width: 50%; height: 100%; background-color: black;" v-if="Plugin.currentPlugin">
|
|
<h2 style="padding: 10px; font-weight: lighter;">Results</h2>
|
|
<div style="position: absolute; top: 10px; right: 10px;">
|
|
<v-btn @click="copyClipboard(Testing.lastResult)" v-if="Testing.lastResult && !Testing.lastResultError">Copy</v-btn>
|
|
</div>
|
|
<div v-if="!Testing.lastResult && !Testing.lastResultError" style="padding: 10px; font-weight: lighter;">
|
|
No test done yet
|
|
</div>
|
|
<div v-if="Testing.lastResult && !Testing.lastResultError" class="testResult">{{Testing.lastResult}}</div>
|
|
<div v-if="Testing.lastResultError" class="testResult exception">{{Testing.lastResultError}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="page" v-if="page == 'Integration'">
|
|
<v-card style="margin-top: 20px; margin-bottom: 20px; margin-left: auto; margin-right: auto; width: 500px;" v-if="!Plugin.currentPlugin">
|
|
<v-card-title>
|
|
No Plugin Loaded
|
|
</v-card-title>
|
|
</v-card-header>
|
|
<v-card-text>
|
|
<div>
|
|
Load a plugin before doing integration testing.
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
<v-card style="width: 500px; margin-left: auto; margin-right: auto; margin-top: 20px;"
|
|
v-if="Plugin.currentPluginError">
|
|
<v-card-text>
|
|
<div>
|
|
<h2 style="color: red">Errors in Plugin</h2>
|
|
Its best to fix errors before doing any integration testing
|
|
</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
<v-card style="margin-top: 20px; margin-bottom: 20px; margin-left: auto; margin-right: auto; width: 500px;" v-if="Plugin.currentPlugin">
|
|
<v-card-title>
|
|
Integration Testing
|
|
</v-card-title>
|
|
</v-card-header>
|
|
<v-card-text>
|
|
<div>
|
|
<div style="margin-bottom: 10px;">
|
|
Integration testing allows you to upload your loaded plugin onto your phone, and get logs below to find any exceptions in actual usage.
|
|
</div>
|
|
<div v-if="Integration.lastInjectTime">
|
|
Last Injected: {{Integration.lastInjectTime}} <br />
|
|
Click Inject Plugin again to update to last version.
|
|
</div>
|
|
<div v-if="!Integration.lastInjectTime">
|
|
Plugin is not yet injected. Click "Inject Plugin" to load the plugin on your phone.
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn @click="injectDevPlugin()">Inject Plugin</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
<v-card style="margin: 20px;" v-if="Plugin.currentPlugin">
|
|
<v-card-title>
|
|
Device Logs
|
|
</v-card-title>
|
|
</v-card-header>
|
|
<v-card-text>
|
|
<div class="logContainer">
|
|
<div class="logLine" v-for="line in Integration.logs" :class="{exception: line.type == 'EXCEPTION', system: line.type == 'SYSTEM'}">
|
|
<div class="logType" style="vertical-align: top;">
|
|
[{{line.type}}]
|
|
</div>
|
|
<div class="logMsg">{{line.log}}</div>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn>Clear</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</div>
|
|
|
|
<div class="page" v-if="page == 'Settings'">
|
|
<v-card style="margin-top: 20px; margin-bottom: 20px; margin-left: auto; margin-right: auto; width: 500px;">
|
|
<v-card-title>
|
|
Settings
|
|
</v-card-title>
|
|
</v-card-header>
|
|
<v-card-text>
|
|
<div>
|
|
<div style="height: 30px;">
|
|
<v-checkbox label="Enable on Reload" v-model="settings.enableOnReload"></v-checkbox>
|
|
</div>
|
|
<div style="height: 30px;">
|
|
<v-checkbox label="Login on Reload" v-model="settings.loginOnReload">></v-checkbox>
|
|
</div>
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn @click="saveSettings()">Save</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</div>
|
|
|
|
</div>
|
|
</v-main>
|
|
</v-app>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.7.1/dist/vuetify.min.js"></script>
|
|
<!--<script src="./dependencies/vue.js"></script>-->
|
|
<!--<script src="./dependencies/vuetify.js"></script>-->
|
|
<script src="./source_docs.js"></script>
|
|
<script src="./source.js"></script>
|
|
<script src="./dev_bridge.js"></script>
|
|
<script>
|
|
IS_TESTING = true;
|
|
let lastScriptTag = null;
|
|
new Vue({
|
|
el: '#app',
|
|
data: {
|
|
page: "Plugin",
|
|
pastPluginUrls: [],
|
|
settings: {},
|
|
Integration: {
|
|
lastLogIndex: -1,
|
|
lastLogDevID: "",
|
|
logs: [],
|
|
lastInjectTime: ""
|
|
},
|
|
Plugin: {
|
|
loadUsingTag: false,
|
|
newPluginUrl: "",
|
|
packagesOverridden: packageOverridesEnabled,
|
|
currentPluginUrl: "",
|
|
currentPlugin: null,
|
|
currentPluginError: "",
|
|
currentScript: "",
|
|
lastLoadTime: "",
|
|
didInitialLoad: false,
|
|
enableOnReload: false,
|
|
isLoggedIn: false
|
|
},
|
|
Testing: {
|
|
requests: sourceDocs.map(x=>{
|
|
x.parameters.forEach(y=>y.value = null);
|
|
return x;
|
|
}),
|
|
lastResult: "",
|
|
lastResultError: ""
|
|
}
|
|
},
|
|
mounted() {
|
|
let existing = localStorage.getItem("pastPlugins");
|
|
if(!existing)
|
|
existing = [];
|
|
else
|
|
existing = JSON.parse(existing);
|
|
|
|
|
|
let settingsStr = localStorage.getItem("settings");
|
|
if(!settingsStr)
|
|
this.settings = {};
|
|
else
|
|
this.settings = JSON.parse(settingsStr);
|
|
|
|
|
|
this.pastPluginUrls = existing.slice(0, 5);
|
|
|
|
this.loadOverrides();
|
|
|
|
window.onerror = (event, source, lineno, colno, error)=>{
|
|
Vue.nextTick(()=>{
|
|
if(error)
|
|
this.Plugin.currentPluginError = error + " (" + lineno + ", " + colno + ")";
|
|
else
|
|
this.Plugin.currentPluginError = "There is an error in your script, check console for info";
|
|
});
|
|
};
|
|
setInterval(()=>{
|
|
try{
|
|
if(!this.Plugin.currentPlugin)
|
|
return;
|
|
|
|
getDevLogs(this.Integration.lastLogIndex, (newLogs)=> {
|
|
if(newLogs.length > 0) {
|
|
let firstLog = newLogs[0];
|
|
let lastLog = newLogs[newLogs.length - 1];
|
|
Vue.nextTick(()=>{
|
|
let lastDevId = this.Integration.lastLogDevID;
|
|
this.Integration.lastLogDevID = lastLog.devId;
|
|
this.Integration.lastLogIndex = lastLog.id;
|
|
for(i = 0; i < newLogs.length; i++) {
|
|
const log = newLogs[i];
|
|
console.log("Log", log);
|
|
if(lastDevId != log.devId) {
|
|
this.Integration.logs = [];
|
|
lastDevId = log.devId;
|
|
this.Integration.logs.unshift({
|
|
id: -1,
|
|
devId: lastDevId,
|
|
message: "New Dev Session: " + lastDevId
|
|
});
|
|
}
|
|
this.Integration.logs.unshift(log)
|
|
};
|
|
});
|
|
}
|
|
});
|
|
}
|
|
catch(ex) {
|
|
console.error("Failed update", ex);
|
|
}
|
|
}, 1000);
|
|
setInterval(()=>{
|
|
try{
|
|
this.isTestLoggedIn();
|
|
}catch(ex){}
|
|
}, 2500);
|
|
},
|
|
methods: {
|
|
loadOverrides() {
|
|
let overridesExisting = localStorage.getItem("overrides");
|
|
if(overridesExisting && overridesExisting != "undefined") {
|
|
try{
|
|
const overrides = JSON.parse(overridesExisting);
|
|
for(override in this.Plugin.packagesOverridden) {
|
|
if(overrides[override])
|
|
this.Plugin.packagesOverridden[override] = true;
|
|
}
|
|
}
|
|
catch(ex) {
|
|
console.error(ex);
|
|
}
|
|
}
|
|
this.Plugin.didInitialLoad = true;
|
|
},
|
|
saveOverrides() {
|
|
if(this.Plugin.packagesOverridden && this.Plugin.didInitialLoad) {
|
|
let overridesExisting = JSON.stringify(this.Plugin.packagesOverridden);
|
|
localStorage.setItem("overrides", overridesExisting);
|
|
}
|
|
},
|
|
loadPlugin(url) {
|
|
Vue.nextTick(()=>{
|
|
this.Plugin.currentPluginUrl = url;
|
|
this.reloadPlugin();
|
|
});
|
|
},
|
|
loginTestPlugin() {
|
|
pluginLoginTestPlugin();
|
|
setTimeout(()=>{
|
|
reloadPackages();
|
|
this.isTestLoggedIn((loggedIn)=>{
|
|
if(loggedIn && this.settings.enableOnReload)
|
|
this.testSource(this.Testing.requests.find(x=>x.title == 'enable'));
|
|
});
|
|
}, 1000);
|
|
},
|
|
logoutTestPlugin() {
|
|
pluginLogoutTestPlugin();
|
|
},
|
|
reloadPlugin() {
|
|
const url = this.Plugin.currentPluginUrl;
|
|
const pluginResp = httpGETBypass(url, {}, "text/json");
|
|
if(pluginResp.code != 200) {
|
|
alert("Failed to get plugin, check log")
|
|
console.error("Failed to get plugin", pluginResp);
|
|
}
|
|
else {
|
|
this.Plugin.currentPlugin = JSON.parse(pluginResp.body);
|
|
this.Plugin.currentPlugin.sourceUrl = url;
|
|
}
|
|
this.Plugin.currentPluginIcon = new URL(this.Plugin.currentPlugin.iconUrl, url).href
|
|
|
|
let currentPastPlugins = this.pastPluginUrls;
|
|
currentPastPlugins = currentPastPlugins.filter(x=>x.toLowerCase() != url.toLowerCase());
|
|
currentPastPlugins.unshift(url);
|
|
this.pastPluginUrls = currentPastPlugins;
|
|
localStorage.setItem("pastPlugins", JSON.stringify(currentPastPlugins));
|
|
|
|
try {
|
|
this.Plugin.warnings = pluginGetWarnings(this.Plugin.currentPlugin);
|
|
}
|
|
catch(ex) {
|
|
alert("Failed to validate config, check log")
|
|
console.error("Failed to validate config", ex);
|
|
return;
|
|
}
|
|
|
|
|
|
if(!this.Plugin.currentPlugin.scriptUrl) {
|
|
alert("Misssing plugin script, check log")
|
|
console.error("Failed to get plugin due to missing script");
|
|
}
|
|
|
|
let absScriptUrl = new URL(this.Plugin.currentPlugin.scriptUrl, url).href;
|
|
console.log("Loading script (Abs):" + absScriptUrl);
|
|
|
|
const scriptResp = httpGETBypass(absScriptUrl, {}, "application/js");
|
|
if(pluginResp.code != 200) {
|
|
alert("Failed to get plugin")
|
|
console.error("Failed to get plugin", pluginResp);
|
|
}
|
|
else {
|
|
this.Plugin.currentScript = scriptResp.body;
|
|
try{
|
|
//TODO: Load packages
|
|
const testPluginPackages = pluginUpdateTestPlugin(this.Plugin.currentPlugin);
|
|
console.log("Required packages:", testPluginPackages);
|
|
applyPackages(testPluginPackages);
|
|
|
|
if(this.Plugin.loadUsingTag)
|
|
{
|
|
this.Plugin.currentPluginError = ""
|
|
//Create script tag
|
|
const scriptUrl = absScriptUrl + "?x=" + new Date().getTime();
|
|
if(lastScriptTag)
|
|
lastScriptTag.parentNode.removeChild(lastScriptTag);
|
|
lastScriptTag = document.createElement('script');
|
|
lastScriptTag.src = scriptUrl;
|
|
lastScriptTag.crossorigin = "anonymous";
|
|
lastScriptTag.onerror = function() {
|
|
Vue.nextTick(()=>{
|
|
this.Plugin.currentPluginError = "Exception loading script: " + scriptUrl;
|
|
});
|
|
}
|
|
document.getElementsByTagName('body')[0].appendChild(lastScriptTag);
|
|
}
|
|
else
|
|
eval(this.Plugin.currentScript);
|
|
|
|
const date = new Date();
|
|
this.Plugin.lastLoadTime =
|
|
(date.getHours()+"").padStart(2, '0') + ":" +
|
|
(date.getMinutes()+"").padStart(2, '0') + ":" +
|
|
(date.getSeconds()+"").padStart(2, '0');
|
|
|
|
|
|
if(this.settings.loginOnReload) {
|
|
this.loginTestPlugin()
|
|
}
|
|
else if(this.settings.enableOnReload)
|
|
this.testSource(this.Testing.requests.find(x=>x.title == 'enable'));
|
|
}
|
|
catch(ex) {
|
|
alert("Failed to load plugin script, check log");
|
|
console.error("Failed to load plugin script", ex);
|
|
this.Plugin.currentPluginError = "Exception loading script:\n" + ex;
|
|
}
|
|
}
|
|
},
|
|
isTestLoggedIn(cb) {
|
|
pluginIsLoggedIn((isLoggedIn)=> {
|
|
Vue.nextTick(()=>{
|
|
const hasChanged = isLoggedIn != isLoggedIn;
|
|
this.Plugin.isLoggedIn = isLoggedIn;
|
|
|
|
if(hasChanged)
|
|
clearPackages();
|
|
|
|
if(cb)
|
|
cb(isLoggedIn);
|
|
});
|
|
}, (ex)=> {
|
|
if(cb)
|
|
cb(false);
|
|
});
|
|
},
|
|
injectDevPlugin() {
|
|
this.Integration.lastLogDevID = uploadDevPlugin(this.Plugin.currentPlugin);
|
|
this.Integration.logs = [
|
|
{
|
|
id: -1,
|
|
devId: this.Integration.lastLogDevID,
|
|
type: 'SYSTEM',
|
|
log: 'New Injected Session [' + this.Integration.lastLogDevID + ']'
|
|
}
|
|
];
|
|
const date = new Date();
|
|
this.Integration.lastInjectTime =
|
|
(date.getHours()+"").padStart(2, '0') + ":" +
|
|
(date.getMinutes()+"").padStart(2, '0') + ":" +
|
|
(date.getSeconds()+"").padStart(2, '0');
|
|
},
|
|
testSource(req) {
|
|
const name = req.title;
|
|
const parameterVals = req.parameters.map(x=>{
|
|
if(x.value && x.value.startsWith && x.value.startsWith("json:"))
|
|
return JSON.parse(x.value.substring(5));
|
|
return x.value
|
|
});
|
|
|
|
if(name == "enable") {
|
|
if(parameterVals.length > 0)
|
|
parameterVals[0] = this.Plugin.currentPlugin;
|
|
else
|
|
parameterVals.push(this.Plugin.currentPlugin);
|
|
if(parameterVals.length > 1)
|
|
parameterVals[1] = __DEV_SETTINGS;
|
|
else
|
|
parameterVals.push(__DEV_SETTINGS);
|
|
}
|
|
|
|
const func = source[name];
|
|
if(!func)
|
|
alert("Test func not found");
|
|
|
|
try {
|
|
const result = func(...parameterVals);
|
|
console.log("Result for " + req.title, result);
|
|
this.Testing.lastResult = "//Results [" + name + "]\n" +
|
|
JSON.stringify(result, null, 3);
|
|
this.Testing.lastResultError = "";
|
|
}
|
|
catch(ex) {
|
|
console.error("Failed to run test for " + req.title, ex);
|
|
this.Testing.lastResult = ""
|
|
if(ex.message)
|
|
this.Testing.lastResultError = "//Results [" + name + "]\n\n" +
|
|
"Error: " + ex.message + "\n\n" + ex.stack;
|
|
else
|
|
this.Testing.lastResultError = "//Results [" + name + "]\n\n" +
|
|
"Error: " + ex;
|
|
}
|
|
},
|
|
showTestResults(results) {
|
|
|
|
},
|
|
copyClipboard(cpy) {
|
|
if(navigator.clipboard)
|
|
navigator.clipboard.writeText(cpy);
|
|
else {
|
|
var textArea = document.createElement("textarea");
|
|
textArea.value = cpy;
|
|
textArea.style.top = "0";
|
|
textArea.style.left = "0";
|
|
textArea.style.position = "fixed";
|
|
document.body.appendChild(textArea);
|
|
textArea.focus();
|
|
textArea.select();
|
|
try {
|
|
document.execCommand('copy');
|
|
} catch (err) { console.error('Failed to copy', err); }
|
|
document.body.removeChild(textArea);
|
|
}
|
|
},
|
|
|
|
saveSettings() {
|
|
let settingsStr = JSON.stringify(this.settings);
|
|
localStorage.setItem("settings", settingsStr);
|
|
}
|
|
},
|
|
vuetify: new Vuetify({
|
|
theme: {
|
|
dark: true
|
|
}
|
|
}),
|
|
});
|
|
function copyTextToClipboard(text) {
|
|
if (!navigator.clipboard) {
|
|
fallbackCopyTextToClipboard(text);
|
|
return;
|
|
}
|
|
navigator.clipboard.writeText(text).then(function() {
|
|
console.log('Async: Copying to clipboard was successful!');
|
|
}, function(err) {
|
|
console.error('Async: Could not copy text: ', err);
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |