mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-27 01:41:44 +02:00
Added wip plugin store
- Added plugin store snippet - Added plugin list sync functions - Work in progress install / uninstall plugin function
This commit is contained in:
@ -185,6 +185,8 @@
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<button class="ui violet button" onclick="openPluginStore();"><i class="cart arrow down icon"></i>Get More Plugins!</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -563,6 +565,11 @@ function getPluginInfo(pluginId, btn){
|
||||
showSideWrapper("snippet/pluginInfo.html?t=" + Date.now() + "#" + payload);
|
||||
}
|
||||
|
||||
function openPluginStore(){
|
||||
//Open plugin store in extended mode
|
||||
showSideWrapper("snippet/pluginstore.html?t=" + Date.now(), true);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -197,6 +197,12 @@ body.darkTheme .menubar{
|
||||
max-width: calc(80% - 1em);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 478px) {
|
||||
.sideWrapper.extendedMode {
|
||||
max-width: calc(100% - 1em);
|
||||
}
|
||||
}
|
||||
|
||||
.sideWrapper .content{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
258
src/web/snippet/pluginstore.html
Normal file
258
src/web/snippet/pluginstore.html
Normal file
@ -0,0 +1,258 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<title>Plugin Store</title>
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
#pluginList{
|
||||
padding: 1em;
|
||||
border: 1px solid #ccc;
|
||||
height: 500px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
body.darkTheme #pluginList .header{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.installablePlugin{
|
||||
position: relative;
|
||||
}
|
||||
.installablePlugin .action{
|
||||
position: absolute;
|
||||
top: 0.4em;
|
||||
right: 0.4em;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
#pluginList .item .image {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<link rel="stylesheet" href="../darktheme.css">
|
||||
<script src="../script/darktheme.js"></script>
|
||||
<br>
|
||||
<div class="ui container">
|
||||
<div class="ui fluid search">
|
||||
<div class="ui fluid icon input">
|
||||
<input id="searchInput" class="prompt" type="text" placeholder="Search plugins">
|
||||
<i class="search icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui divided items" id="pluginList">
|
||||
|
||||
</div>
|
||||
<button class="ui basic button" onclick="forceResyncPlugins();"><i class="ui green refresh icon"></i> Update Plugin List</button>
|
||||
<div class="ui divider"></div>
|
||||
<div class="ui basic segment advanceoptions">
|
||||
<div class="ui accordion advanceSettings">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
Advance Settings
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Plugin Store URLs</p>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<textarea id="pluginStoreURLs" rows="5"></textarea>
|
||||
<label>Enter plugin store URLs, separating each URL with a new line</label>
|
||||
</div>
|
||||
<button class="ui basic button" onclick="savePluginStoreURLs()">
|
||||
<i class="ui green save icon"></i>Save
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<div class="field" >
|
||||
<button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
|
||||
</div>
|
||||
<br><br><br><br>
|
||||
</div>
|
||||
<script>
|
||||
let availablePlugins = [];
|
||||
let installedPlugins = [];
|
||||
$(".accordion").accordion();
|
||||
|
||||
function initStoreList(){
|
||||
$.get("/api/plugins/list", function(data) {
|
||||
if (data.error != undefined) {
|
||||
parent.msgbox(data.error, false);
|
||||
return;
|
||||
}else{
|
||||
installedPlugins = data || [];
|
||||
console.log(installedPlugins);
|
||||
}
|
||||
|
||||
$.cjax({
|
||||
url: '/api/plugins/store/list',
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
if (data.error != undefined) {
|
||||
parent.msgbox(data.error, false);
|
||||
}else{
|
||||
availablePlugins = data || [];
|
||||
populatePluginList(availablePlugins);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
initStoreList();
|
||||
|
||||
/* Plugin Search */
|
||||
function searchPlugins() {
|
||||
const query = document.getElementById('searchInput').value.toLowerCase();
|
||||
const items = document.querySelectorAll('#pluginList .item');
|
||||
if (query.trim() === '') {
|
||||
items.forEach(item => {
|
||||
item.style.display = '';
|
||||
});
|
||||
return;
|
||||
}
|
||||
items.forEach(item => {
|
||||
const name = item.querySelector('.header').textContent.toLowerCase();
|
||||
const description = item.querySelector('.description p').textContent.toLowerCase();
|
||||
const author = item.querySelector('.meta span:nth-child(2)').textContent.toLowerCase();
|
||||
const id = item.querySelector('.extra button').getAttribute('onclick').match(/'(.*?)'/)[1].toLowerCase();
|
||||
|
||||
if (name.includes(query) || description.includes(query) || author.includes(query) || id.includes(query)) {
|
||||
item.style.display = '';
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//Bind search function to input field and Enter key
|
||||
document.getElementById('searchInput').addEventListener('input', searchPlugins);
|
||||
document.getElementById('searchInput').addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Enter') {
|
||||
searchPlugins();
|
||||
}
|
||||
});
|
||||
|
||||
function forceResyncPlugins() {
|
||||
$.cjax({
|
||||
url: '/api/plugins/store/resync',
|
||||
type: 'POST',
|
||||
success: function(data) {
|
||||
if (data.error != undefined) {
|
||||
parent.msgbox(data.error, false);
|
||||
} else {
|
||||
parent.msgbox("Plugin list updated successfully", true);
|
||||
initStoreList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Plugin Store */
|
||||
function populatePluginList(plugins) {
|
||||
const pluginList = document.getElementById('pluginList');
|
||||
pluginList.innerHTML = ''; // Clear existing items
|
||||
plugins.forEach(plugin => {
|
||||
console.log(plugin);
|
||||
let thisPluginIsInstalled = false;
|
||||
installedPlugins.forEach(installedPlugin => {
|
||||
if (installedPlugin.Spec.id == plugin.PluginIntroSpect.id) {
|
||||
thisPluginIsInstalled = true;
|
||||
}
|
||||
});
|
||||
const item = `
|
||||
<div class="item installablePlugin" plugin_id="${plugin.PluginIntroSpect.id}">
|
||||
<div class="ui tiny image">
|
||||
<img src="${plugin.IconPath}" alt="${plugin.PluginIntroSpect.name}">
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="header">${plugin.PluginIntroSpect.name}</div>
|
||||
<div class="meta">
|
||||
<span>Version: ${plugin.PluginIntroSpect.version_major}.${plugin.PluginIntroSpect.version_minor}.${plugin.PluginIntroSpect.version_patch}</span>
|
||||
<span>${plugin.PluginIntroSpect.author}</span>
|
||||
<span><a href="${plugin.PluginIntroSpect.url}">Website</a></span>
|
||||
</div>
|
||||
<div class="description">
|
||||
<p>${plugin.PluginIntroSpect.description}</p>
|
||||
</div>
|
||||
<div class="action">
|
||||
${thisPluginIsInstalled
|
||||
? `<button class="ui basic circular red button" onclick="uninstallPlugin('${plugin.PluginIntroSpect.id}')"><i class="ui trash icon"></i> Remove</button>`
|
||||
: `<button class="ui basic circular button" onclick="installPlugin('${plugin.PluginIntroSpect.id}')"><i class="ui download icon"></i> Install</button>`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#pluginList').append(item);
|
||||
});
|
||||
}
|
||||
|
||||
/* Plugin Actions */
|
||||
function installPlugin(pluginId) {
|
||||
$.cjax({
|
||||
url: '/api/plugins/store/install',
|
||||
type: 'POST',
|
||||
data: { pluginId },
|
||||
success: function(data) {
|
||||
if (data.error != undefined) {
|
||||
parent.msgbox(data.error, false);
|
||||
} else {
|
||||
parent.msgbox("Plugin installed successfully", true);
|
||||
initStoreList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallPlugin(pluginId) {
|
||||
$.cjax({
|
||||
url: '/api/plugins/store/uninstall',
|
||||
type: 'POST',
|
||||
data: { pluginId },
|
||||
success: function(data) {
|
||||
if (data.error != undefined) {
|
||||
parent.msgbox(data.error, false);
|
||||
} else {
|
||||
parent.msgbox("Plugin uninstalled successfully", true);
|
||||
initStoreList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeThisWrapper(){
|
||||
parent.hideSideWrapper(true);
|
||||
}
|
||||
|
||||
/* Advanced Options */
|
||||
function savePluginManagerURLs() {
|
||||
const urls = document.getElementById('pluginStoreURLs').value.split('\n').map(url => url.trim()).filter(url => url !== '');
|
||||
console.log('Saving URLs:', urls);
|
||||
// Add your logic to save the URLs here, e.g., send them to the server
|
||||
$.cjax({
|
||||
url: '/api/plugins/store/saveURLs',
|
||||
type: 'POST',
|
||||
data: { urls },
|
||||
success: function(data) {
|
||||
if (data.error != undefined) {
|
||||
parent.msgbox(data.error, false);
|
||||
} else {
|
||||
parent.msgbox("URLs saved successfully", true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user