2017-10-27 01:00:52 +08:00
|
|
|
var onUninstall, onInstall;
|
2019-01-09 22:54:35 +08:00
|
|
|
const Plugins = {
|
2017-10-27 01:00:52 +08:00
|
|
|
Vue: [], //Vue Object
|
|
|
|
installed: [], //Simple List of Names
|
|
|
|
json: undefined, //Json from website
|
2021-08-27 21:48:32 +08:00
|
|
|
download_stats: {},
|
2019-02-04 04:09:35 +08:00
|
|
|
all: [], //Vue Object Data
|
2019-07-18 00:02:07 +08:00
|
|
|
registered: {},
|
|
|
|
devReload() {
|
2018-03-29 02:48:11 +08:00
|
|
|
var reloads = 0;
|
2019-02-04 04:09:35 +08:00
|
|
|
for (var i = Plugins.all.length-1; i >= 0; i--) {
|
2020-04-26 02:25:07 +08:00
|
|
|
if (Plugins.all[i].source == 'file') {
|
2019-02-04 04:09:35 +08:00
|
|
|
Plugins.all[i].reload()
|
2018-03-29 02:48:11 +08:00
|
|
|
reloads++;
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
|
|
|
Blockbench.showQuickMessage(tl('message.plugin_reload', [reloads]))
|
2018-03-29 02:48:11 +08:00
|
|
|
console.log('Reloaded '+reloads+ ' plugin'+pluralS(reloads))
|
2019-07-18 00:02:07 +08:00
|
|
|
},
|
|
|
|
sort() {
|
2022-02-11 02:21:50 +08:00
|
|
|
Plugins.all.sort((a, b) => {
|
|
|
|
if (a.tags.find(tag => tag.match(/deprecated/i))) return 1;
|
|
|
|
if (b.tags.find(tag => tag.match(/deprecated/i))) return -1;
|
2021-08-27 21:48:32 +08:00
|
|
|
let download_difference = (Plugins.download_stats[b.id] || 0) - (Plugins.download_stats[a.id] || 0);
|
|
|
|
if (download_difference) {
|
|
|
|
return download_difference
|
|
|
|
} else {
|
|
|
|
return sort_collator.compare(a.title, b.title);
|
|
|
|
}
|
2019-07-18 00:02:07 +08:00
|
|
|
});
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
|
|
|
}
|
2020-04-26 02:25:07 +08:00
|
|
|
StateMemory.init('installed_plugins', 'array')
|
|
|
|
Plugins.installed = StateMemory.installed_plugins;
|
2017-10-27 01:00:52 +08:00
|
|
|
|
2019-02-04 04:09:35 +08:00
|
|
|
class Plugin {
|
|
|
|
constructor(id, data) {
|
2019-07-18 00:02:07 +08:00
|
|
|
this.id = id||'unknown';
|
2019-02-04 04:09:35 +08:00
|
|
|
this.installed = false;
|
|
|
|
this.expanded = false;
|
|
|
|
this.title = '';
|
|
|
|
this.author = '';
|
|
|
|
this.description = '';
|
|
|
|
this.about = '';
|
|
|
|
this.icon = '';
|
2021-05-25 01:45:40 +08:00
|
|
|
this.tags = [];
|
2021-08-07 21:13:20 +08:00
|
|
|
this.version = '0.0.1';
|
2020-11-20 05:39:00 +08:00
|
|
|
this.variant = 'both';
|
2019-02-04 04:09:35 +08:00
|
|
|
this.min_version = '';
|
2020-10-12 01:53:22 +08:00
|
|
|
this.max_version = '';
|
2020-04-26 02:25:07 +08:00
|
|
|
this.source = 'store'
|
2021-06-11 22:31:30 +08:00
|
|
|
this.await_loading = false;
|
2019-07-18 00:02:07 +08:00
|
|
|
|
|
|
|
this.extend(data)
|
|
|
|
|
|
|
|
Plugins.all.safePush(this);
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
|
|
|
extend(data) {
|
2019-07-18 00:02:07 +08:00
|
|
|
if (!(data instanceof Object)) return this;
|
2019-02-04 04:09:35 +08:00
|
|
|
Merge.boolean(this, data, 'installed')
|
|
|
|
Merge.boolean(this, data, 'expanded')
|
|
|
|
Merge.string(this, data, 'title')
|
|
|
|
Merge.string(this, data, 'author')
|
|
|
|
Merge.string(this, data, 'description')
|
|
|
|
Merge.string(this, data, 'about')
|
|
|
|
Merge.string(this, data, 'icon')
|
2021-08-07 21:13:20 +08:00
|
|
|
Merge.string(this, data, 'version')
|
2019-02-04 04:09:35 +08:00
|
|
|
Merge.string(this, data, 'variant')
|
|
|
|
Merge.string(this, data, 'min_version')
|
2021-06-11 22:31:30 +08:00
|
|
|
Merge.boolean(this, data, 'await_loading');
|
2021-06-16 02:24:01 +08:00
|
|
|
if (data.tags instanceof Array) this.tags.safePush(...data.tags.slice(0, 3));
|
2019-07-18 00:02:07 +08:00
|
|
|
|
|
|
|
Merge.function(this, data, 'onload')
|
|
|
|
Merge.function(this, data, 'onunload')
|
|
|
|
Merge.function(this, data, 'oninstall')
|
|
|
|
Merge.function(this, data, 'onuninstall')
|
2019-02-04 04:09:35 +08:00
|
|
|
return this;
|
|
|
|
}
|
2021-09-08 00:53:11 +08:00
|
|
|
get name() {
|
|
|
|
return this.title;
|
|
|
|
}
|
2020-08-14 04:50:54 +08:00
|
|
|
async install(first, cb) {
|
2019-02-04 04:09:35 +08:00
|
|
|
var scope = this;
|
2019-07-18 00:02:07 +08:00
|
|
|
Plugins.registered[this.id] = this;
|
2020-08-14 04:50:54 +08:00
|
|
|
return await new Promise((resolve, reject) => {
|
2021-02-28 07:42:01 +08:00
|
|
|
$.getScript(Plugins.path + scope.id + '.js', () => {
|
2020-08-14 04:50:54 +08:00
|
|
|
if (cb) cb.bind(scope)()
|
|
|
|
scope.bindGlobalData(first)
|
|
|
|
if (first && scope.oninstall) {
|
|
|
|
scope.oninstall()
|
|
|
|
}
|
2021-02-24 04:56:36 +08:00
|
|
|
if (first) Blockbench.showQuickMessage(tl('message.installed_plugin', [this.title]));
|
2020-08-14 04:50:54 +08:00
|
|
|
resolve()
|
2021-02-28 07:42:01 +08:00
|
|
|
}).fail(() => {
|
2020-08-14 04:50:54 +08:00
|
|
|
if (isApp) {
|
|
|
|
console.log('Could not find file of plugin "'+scope.id+'". Uninstalling it instead.')
|
|
|
|
scope.uninstall()
|
|
|
|
}
|
2021-02-24 04:56:36 +08:00
|
|
|
if (first) Blockbench.showQuickMessage(tl('message.installed_plugin_fail', [this.title]));
|
|
|
|
reject()
|
2020-08-14 04:50:54 +08:00
|
|
|
})
|
|
|
|
this.remember()
|
|
|
|
scope.installed = true;
|
2019-02-04 04:09:35 +08:00
|
|
|
})
|
|
|
|
}
|
2019-07-18 00:02:07 +08:00
|
|
|
bindGlobalData() {
|
2019-02-04 04:09:35 +08:00
|
|
|
var scope = this;
|
|
|
|
if (onUninstall) {
|
2019-07-18 00:02:07 +08:00
|
|
|
scope.onuninstall = onUninstall
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
2019-07-18 00:02:07 +08:00
|
|
|
if (onUninstall) {
|
|
|
|
scope.onuninstall = onUninstall
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
2021-03-04 00:50:30 +08:00
|
|
|
if (window.plugin_data) {
|
|
|
|
console.warn(`plugin_data is deprecated. Please use Plugin.register instead. (${plugin_data.id || 'unknown plugin'})`)
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
window.onInstall = window.onUninstall = window.plugin_data = undefined
|
|
|
|
return this;
|
|
|
|
}
|
2020-08-14 04:50:54 +08:00
|
|
|
async download(first) {
|
2019-02-04 04:09:35 +08:00
|
|
|
var scope = this;
|
2021-10-22 21:07:01 +08:00
|
|
|
function register() {
|
|
|
|
jQuery.ajax({
|
|
|
|
url: 'https://blckbn.ch/api/event/install_plugin',
|
|
|
|
type: 'POST',
|
|
|
|
data: {
|
|
|
|
plugin: scope.id
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
if (!isApp) {
|
2021-10-22 21:07:01 +08:00
|
|
|
if (first) register();
|
2020-12-07 05:44:55 +08:00
|
|
|
return await scope.install(first)
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
2020-08-14 04:50:54 +08:00
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
var file = originalFs.createWriteStream(Plugins.path+this.id+'.js')
|
2021-07-20 03:20:18 +08:00
|
|
|
https.get('https://cdn.jsdelivr.net/gh/JannisX11/blockbench-plugins/plugins/'+this.id+'.js', function(response) {
|
2020-08-14 04:50:54 +08:00
|
|
|
response.pipe(file);
|
|
|
|
response.on('end', function() {
|
|
|
|
setTimeout(async function() {
|
|
|
|
await scope.install(first);
|
|
|
|
resolve()
|
2021-06-11 22:31:30 +08:00
|
|
|
}, 20)
|
2021-10-22 21:07:01 +08:00
|
|
|
if (first) register();
|
2020-08-14 04:50:54 +08:00
|
|
|
})
|
|
|
|
});
|
2019-02-04 04:09:35 +08:00
|
|
|
});
|
|
|
|
}
|
2020-08-14 04:50:54 +08:00
|
|
|
async loadFromFile(file, first) {
|
2019-02-04 04:09:35 +08:00
|
|
|
var scope = this;
|
2019-07-19 23:31:22 +08:00
|
|
|
if (!isApp && !first) return this;
|
2019-07-18 00:02:07 +08:00
|
|
|
if (first) {
|
2019-02-04 04:09:35 +08:00
|
|
|
if (isApp) {
|
|
|
|
if (!confirm(tl('message.load_plugin_app'))) return;
|
|
|
|
} else {
|
|
|
|
if (!confirm(tl('message.load_plugin_web'))) return;
|
|
|
|
}
|
|
|
|
}
|
2019-07-19 23:31:22 +08:00
|
|
|
|
2021-05-25 01:45:40 +08:00
|
|
|
this.id = pathToName(file.path);
|
2019-07-19 23:31:22 +08:00
|
|
|
Plugins.registered[this.id] = this;
|
2021-05-25 01:45:40 +08:00
|
|
|
localStorage.setItem('plugin_dev_path', file.path);
|
|
|
|
Plugins.all.safePush(this);
|
|
|
|
this.source = 'file';
|
2021-06-16 02:24:01 +08:00
|
|
|
this.tags.safePush('Local');
|
2020-08-14 04:50:54 +08:00
|
|
|
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
|
|
|
|
if (isApp) {
|
|
|
|
$.getScript(file.path, () => {
|
|
|
|
if (window.plugin_data) {
|
|
|
|
scope.id = (plugin_data && plugin_data.id)||pathToName(file.path)
|
|
|
|
scope.extend(plugin_data)
|
|
|
|
scope.bindGlobalData()
|
|
|
|
}
|
2020-11-20 05:39:00 +08:00
|
|
|
if (first && scope.oninstall) {
|
|
|
|
scope.oninstall()
|
|
|
|
}
|
|
|
|
scope.installed = true;
|
|
|
|
scope.path = file.path;
|
|
|
|
this.remember();
|
|
|
|
Plugins.sort();
|
2020-08-14 04:50:54 +08:00
|
|
|
resolve()
|
|
|
|
}).fail(reject)
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
eval(file.content);
|
|
|
|
} catch (err) {
|
|
|
|
reject(err)
|
|
|
|
}
|
|
|
|
if (!Plugins.registered && window.plugin_data) {
|
|
|
|
scope.id = (plugin_data && plugin_data.id)||scope.id
|
2019-07-19 23:31:22 +08:00
|
|
|
scope.extend(plugin_data)
|
|
|
|
scope.bindGlobalData()
|
|
|
|
}
|
|
|
|
scope.installed = true
|
2020-04-26 02:25:07 +08:00
|
|
|
this.remember()
|
2019-07-19 23:31:22 +08:00
|
|
|
Plugins.sort()
|
2020-08-14 04:50:54 +08:00
|
|
|
resolve()
|
2019-07-19 23:31:22 +08:00
|
|
|
}
|
2020-08-14 04:50:54 +08:00
|
|
|
})
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
2020-12-07 05:44:55 +08:00
|
|
|
async loadFromURL(url, first) {
|
2020-04-26 02:25:07 +08:00
|
|
|
if (first) {
|
|
|
|
if (isApp) {
|
|
|
|
if (!confirm(tl('message.load_plugin_app'))) return;
|
|
|
|
} else {
|
|
|
|
if (!confirm(tl('message.load_plugin_web'))) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.id = pathToName(url)
|
|
|
|
Plugins.registered[this.id] = this;
|
|
|
|
localStorage.setItem('plugin_dev_path', url)
|
|
|
|
Plugins.all.safePush(this)
|
2021-06-16 02:24:01 +08:00
|
|
|
this.tags.safePush('Remote');
|
2020-04-26 02:25:07 +08:00
|
|
|
|
|
|
|
this.source = 'url';
|
2020-12-07 05:44:55 +08:00
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
$.getScript(url, () => {
|
|
|
|
if (window.plugin_data) {
|
|
|
|
this.id = (plugin_data && plugin_data.id)||pathToName(url)
|
|
|
|
this.extend(plugin_data)
|
|
|
|
this.bindGlobalData()
|
|
|
|
}
|
|
|
|
this.installed = true
|
|
|
|
this.path = url
|
|
|
|
this.remember()
|
|
|
|
Plugins.sort()
|
|
|
|
// Save
|
|
|
|
if (isApp) {
|
|
|
|
var file = originalFs.createWriteStream(Plugins.path+this.id+'.js')
|
|
|
|
https.get(url, (response) => {
|
|
|
|
response.pipe(file);
|
|
|
|
response.on('end', resolve)
|
|
|
|
}).on('error', reject);
|
|
|
|
} else {
|
|
|
|
resolve()
|
|
|
|
}
|
|
|
|
}).fail(() => {
|
|
|
|
if (isApp) {
|
|
|
|
this.install().then(resolve).catch(resolve)
|
|
|
|
}
|
|
|
|
})
|
2020-04-26 02:25:07 +08:00
|
|
|
})
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
remember(id = this.id, path = this.path) {
|
|
|
|
if (Plugins.installed.find(plugin => plugin.id == this.id)) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
Plugins.installed.push({
|
|
|
|
id: id,
|
|
|
|
path: path,
|
|
|
|
source: this.source
|
|
|
|
})
|
|
|
|
StateMemory.save('installed_plugins')
|
|
|
|
return this;
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
uninstall() {
|
2019-12-18 00:44:27 +08:00
|
|
|
try {
|
|
|
|
this.unload();
|
|
|
|
if (this.onuninstall) {
|
|
|
|
this.onuninstall();
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
console.log('Error in unload or uninstall method: ', err);
|
2019-07-18 00:02:07 +08:00
|
|
|
}
|
|
|
|
delete Plugins.registered[this.id];
|
2020-04-26 02:25:07 +08:00
|
|
|
let in_installed = Plugins.installed.find(plugin => plugin.id == this.id);
|
|
|
|
Plugins.installed.remove(in_installed);
|
|
|
|
StateMemory.save('installed_plugins')
|
2019-07-18 00:02:07 +08:00
|
|
|
this.installed = false;
|
|
|
|
|
2020-04-26 02:25:07 +08:00
|
|
|
if (isApp && this.source !== 'store') {
|
2019-02-04 04:09:35 +08:00
|
|
|
Plugins.all.remove(this)
|
2020-12-07 05:44:55 +08:00
|
|
|
}
|
|
|
|
if (isApp && this.source != 'file') {
|
2020-04-26 02:25:07 +08:00
|
|
|
var filepath = Plugins.path + this.id + '.js'
|
2019-07-18 00:02:07 +08:00
|
|
|
if (fs.existsSync(filepath)) {
|
|
|
|
fs.unlink(filepath, (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(err);
|
|
|
|
}
|
|
|
|
});
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
2020-04-26 02:25:07 +08:00
|
|
|
StateMemory.save('installed_plugins')
|
2019-02-04 04:09:35 +08:00
|
|
|
return this;
|
|
|
|
}
|
2019-07-18 00:02:07 +08:00
|
|
|
unload() {
|
|
|
|
if (this.onunload) {
|
|
|
|
this.onunload()
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
reload() {
|
2020-04-26 02:25:07 +08:00
|
|
|
if (!isApp && this.source == 'file') return this;
|
|
|
|
|
2019-07-18 00:02:07 +08:00
|
|
|
this.unload()
|
2021-08-09 04:01:53 +08:00
|
|
|
this.tags.empty();
|
2019-07-18 00:02:07 +08:00
|
|
|
Plugins.all.remove(this)
|
2020-04-26 02:25:07 +08:00
|
|
|
|
|
|
|
if (this.source == 'file') {
|
|
|
|
this.loadFromFile({path: this.path}, false)
|
|
|
|
|
|
|
|
} else if (this.source == 'url') {
|
|
|
|
this.loadFromURL(this.path, false)
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
return this;
|
|
|
|
}
|
2020-04-26 02:25:07 +08:00
|
|
|
isReloadable() {
|
|
|
|
return (this.source == 'file' && isApp) || (this.source == 'url')
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
isInstallable() {
|
|
|
|
var scope = this;
|
|
|
|
var result =
|
|
|
|
scope.variant === 'both' ||
|
|
|
|
(
|
|
|
|
isApp === (scope.variant === 'desktop') &&
|
|
|
|
isApp !== (scope.variant === 'web')
|
|
|
|
);
|
|
|
|
if (result && scope.min_version) {
|
2020-10-12 01:53:22 +08:00
|
|
|
result = Blockbench.isOlderThan(scope.min_version) ? 'outdated_client' : true;
|
|
|
|
}
|
|
|
|
if (result && scope.max_version) {
|
|
|
|
result = Blockbench.isNewerThan(scope.max_version) ? 'outdated_plugin' : true
|
|
|
|
}
|
|
|
|
if (result === false) {
|
2019-02-04 04:09:35 +08:00
|
|
|
result = (scope.variant === 'web') ? 'web_only' : 'app_only'
|
|
|
|
}
|
|
|
|
return (result === true) ? true : tl('dialog.plugins.'+result);
|
|
|
|
}
|
|
|
|
toggleInfo(force) {
|
2021-08-07 21:13:20 +08:00
|
|
|
if (!this.about) return;
|
2019-02-04 04:09:35 +08:00
|
|
|
var scope = this;
|
|
|
|
Plugins.all.forEach(function(p) {
|
|
|
|
if (p !== scope && p.expanded) p.expanded = false;
|
|
|
|
})
|
|
|
|
if (force !== undefined) {
|
|
|
|
this.expanded = force === true
|
|
|
|
} else {
|
|
|
|
this.expanded = this.expanded !== true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
get expandicon() {
|
|
|
|
return this.expanded ? 'expand_less' : 'expand_more'
|
|
|
|
}
|
|
|
|
}
|
2021-04-25 19:50:31 +08:00
|
|
|
// Alias for typescript
|
|
|
|
const BBPlugin = Plugin;
|
|
|
|
|
2019-07-18 00:02:07 +08:00
|
|
|
Plugin.register = function(id, data) {
|
|
|
|
if (typeof id !== 'string' || typeof data !== 'object') {
|
|
|
|
console.warn('Plugin.register: not enough arguments, string and object required.')
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var plugin = Plugins.registered[id];
|
|
|
|
if (!plugin) {
|
|
|
|
plugin = Plugins.registered.unknown;
|
|
|
|
if (plugin) {
|
|
|
|
delete Plugins.registered.unknown;
|
|
|
|
plugin.id = id;
|
|
|
|
Plugins.registered[id] = plugin;
|
|
|
|
}
|
|
|
|
}
|
2020-12-12 21:44:30 +08:00
|
|
|
if (!plugin) {
|
|
|
|
Blockbench.showMessageBox({
|
|
|
|
translateKey: 'load_plugin_failed',
|
|
|
|
message: tl('message.load_plugin_failed.message', [id])
|
|
|
|
})
|
|
|
|
};
|
2019-07-18 00:02:07 +08:00
|
|
|
plugin.extend(data)
|
2019-08-18 00:26:14 +08:00
|
|
|
if (data.icon) plugin.icon = Blockbench.getIconNode(data.icon)
|
2020-10-12 01:53:22 +08:00
|
|
|
if (plugin.isInstallable() == true) {
|
|
|
|
if (plugin.onload instanceof Function) {
|
|
|
|
plugin.onload()
|
|
|
|
}
|
2019-07-18 00:02:07 +08:00
|
|
|
}
|
|
|
|
return plugin;
|
|
|
|
}
|
2019-02-04 04:09:35 +08:00
|
|
|
|
2017-10-27 01:00:52 +08:00
|
|
|
if (isApp) {
|
2019-01-09 22:54:35 +08:00
|
|
|
Plugins.path = app.getPath('userData')+osfs+'plugins'+osfs
|
2017-10-27 01:00:52 +08:00
|
|
|
fs.readdir(Plugins.path, function(err) {
|
2018-10-18 01:50:25 +08:00
|
|
|
if (err) {
|
|
|
|
fs.mkdir(Plugins.path, function(a) {})
|
|
|
|
}
|
2017-10-27 01:00:52 +08:00
|
|
|
})
|
2019-02-04 04:09:35 +08:00
|
|
|
} else {
|
|
|
|
Plugins.path = 'https://cdn.jsdelivr.net/gh/JannisX11/blockbench-plugins/plugins/';
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
2020-09-17 22:50:29 +08:00
|
|
|
|
|
|
|
Plugins.loading_promise = new Promise((resolve, reject) => {
|
2022-01-08 21:22:22 +08:00
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
cache: false,
|
|
|
|
url: 'https://cdn.jsdelivr.net/gh/JannisX11/blockbench-plugins/plugins.json',
|
|
|
|
dataType: 'json',
|
|
|
|
success(data) {
|
|
|
|
Plugins.json = data;
|
|
|
|
resolve();
|
|
|
|
Plugins.loading_promise.resolved = true;
|
|
|
|
},
|
|
|
|
error() {
|
|
|
|
console.log('Could not connect to plugin server')
|
|
|
|
$('#plugin_available_empty').text('Could not connect to plugin server')
|
|
|
|
resolve();
|
|
|
|
Plugins.loading_promise.resolved = true;
|
|
|
|
}
|
|
|
|
});
|
2021-08-27 21:48:32 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
$.getJSON('https://blckbn.ch/api/stats/plugins?weeks=2', data => {
|
|
|
|
Plugins.download_stats = data;
|
|
|
|
if (Plugins.json) {
|
|
|
|
Plugins.sort();
|
|
|
|
}
|
2017-10-27 01:00:52 +08:00
|
|
|
})
|
|
|
|
|
2020-08-14 04:50:54 +08:00
|
|
|
async function loadInstalledPlugins() {
|
2020-09-17 22:50:29 +08:00
|
|
|
if (!Plugins.loading_promise.resolved) {
|
|
|
|
await Plugins.loading_promise;
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
2020-09-17 22:50:29 +08:00
|
|
|
const install_promises = [];
|
2020-12-07 05:44:55 +08:00
|
|
|
// Legacy Plugins Import
|
2020-04-26 02:25:07 +08:00
|
|
|
if (localStorage.getItem('installed_plugins')) {
|
|
|
|
var legacy_plugins = JSON.parse(localStorage.getItem('installed_plugins'))
|
|
|
|
if (legacy_plugins instanceof Array) {
|
|
|
|
legacy_plugins.forEach((string, i) => {
|
|
|
|
if (typeof string == 'string') {
|
|
|
|
if (string.match(/\.js$/)) {
|
|
|
|
Plugins.installed[i] = {
|
|
|
|
id: string.split(/[\\/]/).last().replace(/\.js$/, ''),
|
|
|
|
path: string,
|
|
|
|
source: 'file'
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Plugins.installed[i] = {
|
|
|
|
id: string,
|
|
|
|
source: 'store'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
StateMemory.save('installed_plugins')
|
|
|
|
localStorage.removeItem('installed_plugins')
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
2020-04-30 05:35:47 +08:00
|
|
|
Plugins.installed.replace(Plugins.installed.filter(p => p !== null))
|
2020-12-07 05:44:55 +08:00
|
|
|
|
2021-12-15 05:51:21 +08:00
|
|
|
if (Plugins.json instanceof Object && navigator.onLine) {
|
2019-02-04 04:09:35 +08:00
|
|
|
//From Store
|
2017-10-27 01:00:52 +08:00
|
|
|
for (var id in Plugins.json) {
|
2019-02-04 04:09:35 +08:00
|
|
|
var plugin = new Plugin(id, Plugins.json[id])
|
2020-04-30 05:35:47 +08:00
|
|
|
if (Plugins.installed.find(p => {
|
|
|
|
return p && p.id == id && p.source == 'store'
|
2020-04-26 02:25:07 +08:00
|
|
|
})) {
|
2021-06-11 22:31:30 +08:00
|
|
|
let promise = plugin.download();
|
|
|
|
if (plugin.await_loading) {
|
|
|
|
install_promises.push(promise);
|
|
|
|
}
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
|
|
|
}
|
2019-07-18 00:02:07 +08:00
|
|
|
Plugins.sort();
|
2019-02-04 04:09:35 +08:00
|
|
|
} else if (Plugins.installed.length > 0 && isApp) {
|
2019-07-18 00:02:07 +08:00
|
|
|
//Offline
|
2020-04-26 02:25:07 +08:00
|
|
|
Plugins.installed.forEach(function(plugin) {
|
2019-02-04 04:09:35 +08:00
|
|
|
|
2020-04-26 02:25:07 +08:00
|
|
|
if (plugin.source == 'store') {
|
2020-08-14 04:50:54 +08:00
|
|
|
var promise = new Plugin(plugin.id).install(false, function() {
|
2019-07-19 23:31:22 +08:00
|
|
|
this.extend(window.plugin_data)
|
2019-07-18 00:02:07 +08:00
|
|
|
Plugins.sort()
|
2019-02-04 04:09:35 +08:00
|
|
|
})
|
2020-08-14 04:50:54 +08:00
|
|
|
install_promises.push(promise);
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
2017-10-27 01:00:52 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
if (Plugins.installed.length > 0) {
|
2019-04-08 00:53:33 +08:00
|
|
|
var loaded = []
|
2020-04-26 02:25:07 +08:00
|
|
|
Plugins.installed.forEachReverse(function(plugin) {
|
2019-02-04 04:09:35 +08:00
|
|
|
|
2020-04-26 02:25:07 +08:00
|
|
|
if (plugin.source == 'file') {
|
2019-02-04 04:09:35 +08:00
|
|
|
//Dev Plugins
|
2020-04-26 02:25:07 +08:00
|
|
|
if (isApp && fs.existsSync(plugin.path)) {
|
2020-08-14 04:50:54 +08:00
|
|
|
var instance = new Plugin(plugin.id);
|
|
|
|
install_promises.push(instance.loadFromFile({path: plugin.path}, false));
|
2022-02-14 02:13:01 +08:00
|
|
|
loaded.push(['Local', plugin.id || plugin.path]);
|
2019-07-18 00:02:07 +08:00
|
|
|
} else {
|
2020-04-26 02:25:07 +08:00
|
|
|
Plugins.installed.remove(plugin)
|
2019-07-18 00:02:07 +08:00
|
|
|
}
|
2020-04-26 02:25:07 +08:00
|
|
|
|
|
|
|
} else if (plugin.source == 'url') {
|
2020-08-14 04:50:54 +08:00
|
|
|
var instance = new Plugin(plugin.id);
|
2020-12-07 05:44:55 +08:00
|
|
|
install_promises.push(instance.loadFromURL(plugin.path, false));
|
2022-02-14 02:13:01 +08:00
|
|
|
loaded.push(['URL', plugin.id || plugin.path]);
|
2020-04-26 02:25:07 +08:00
|
|
|
|
|
|
|
} else {
|
2022-02-14 02:13:01 +08:00
|
|
|
loaded.push(['Store', plugin.id]);
|
2019-02-04 04:09:35 +08:00
|
|
|
}
|
|
|
|
})
|
2022-02-14 02:13:01 +08:00
|
|
|
console.log(`Loaded ${loaded.length} plugin${pluralS(loaded.length)}`)
|
|
|
|
let list = {};
|
|
|
|
loaded.forEach(([type, id]) => {
|
|
|
|
list[id] = type;
|
|
|
|
})
|
|
|
|
console.table(list);
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
2020-04-26 02:25:07 +08:00
|
|
|
StateMemory.save('installed_plugins')
|
2017-10-27 01:00:52 +08:00
|
|
|
|
2020-08-14 04:50:54 +08:00
|
|
|
|
|
|
|
install_promises.forEach(promise => {
|
|
|
|
promise.catch(console.error);
|
|
|
|
})
|
|
|
|
return await Promise.allSettled(install_promises);
|
2017-10-27 01:00:52 +08:00
|
|
|
}
|
2018-11-12 04:19:08 +08:00
|
|
|
|
|
|
|
BARS.defineActions(function() {
|
2021-02-20 05:10:47 +08:00
|
|
|
|
|
|
|
Plugins.dialog = new Dialog({
|
|
|
|
id: 'plugins',
|
|
|
|
title: 'dialog.plugins.title',
|
2021-05-22 05:48:39 +08:00
|
|
|
singleButton: true,
|
2021-08-07 21:13:20 +08:00
|
|
|
width: 760,
|
2021-02-20 05:10:47 +08:00
|
|
|
component: {
|
|
|
|
data: {
|
2021-02-24 04:56:36 +08:00
|
|
|
tab: 'installed',
|
2021-02-20 05:10:47 +08:00
|
|
|
search_term: '',
|
|
|
|
items: Plugins.all
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
plugin_search() {
|
|
|
|
var name = this.search_term.toUpperCase()
|
|
|
|
return this.items.filter(item => {
|
2021-02-24 04:56:36 +08:00
|
|
|
if ((this.tab == 'installed') == item.installed) {
|
2021-02-20 05:10:47 +08:00
|
|
|
if (name.length > 0) {
|
|
|
|
return (
|
|
|
|
item.id.toUpperCase().includes(name) ||
|
|
|
|
item.title.toUpperCase().includes(name) ||
|
|
|
|
item.description.toUpperCase().includes(name) ||
|
2022-01-26 22:51:08 +08:00
|
|
|
item.author.toUpperCase().includes(name) ||
|
|
|
|
item.tags.find(tag => tag.toUpperCase().includes(name))
|
2021-02-20 05:10:47 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2021-05-25 01:45:40 +08:00
|
|
|
methods: {
|
2021-10-02 00:43:10 +08:00
|
|
|
getTagClass(tag) {
|
2022-02-11 02:21:50 +08:00
|
|
|
if (tag.match(/^(local|remote)$/i)) {
|
2021-10-02 00:43:10 +08:00
|
|
|
return 'plugin_tag_source'
|
2022-02-11 02:21:50 +08:00
|
|
|
} else if (tag.match(/^minecraft/i)) {
|
2021-10-02 00:43:10 +08:00
|
|
|
return 'plugin_tag_mc'
|
2022-02-11 02:21:50 +08:00
|
|
|
} else if (tag.match(/^deprecated/i)) {
|
|
|
|
return 'plugin_tag_deprecated'
|
2021-05-25 01:45:40 +08:00
|
|
|
}
|
2021-09-21 17:20:10 +08:00
|
|
|
},
|
|
|
|
getIconNode: Blockbench.getIconNode,
|
|
|
|
tl
|
2021-05-25 01:45:40 +08:00
|
|
|
},
|
2021-02-20 05:10:47 +08:00
|
|
|
template: `
|
2021-02-20 20:21:11 +08:00
|
|
|
<div style="margin-top: 10px;">
|
2021-02-20 05:10:47 +08:00
|
|
|
<div class="bar">
|
|
|
|
<div class="tab_bar">
|
2021-02-24 04:56:36 +08:00
|
|
|
<div :class="{open: tab == 'installed'}" @click="tab = 'installed'">${tl('dialog.plugins.installed')}</div>
|
|
|
|
<div :class="{open: tab == 'available'}" @click="tab = 'available'">${tl('dialog.plugins.available')}</div>
|
2021-02-20 05:10:47 +08:00
|
|
|
</div>
|
2021-02-20 20:21:11 +08:00
|
|
|
<search-bar id="plugin_search_bar" v-model="search_term"></search-bar>
|
2021-02-20 05:10:47 +08:00
|
|
|
</div>
|
|
|
|
<ul class="list" id="plugin_list">
|
2021-08-07 21:13:20 +08:00
|
|
|
<li v-for="plugin in plugin_search" v-bind:plugin="plugin.id" v-bind:class="{plugin: true, testing: plugin.fromFile, expanded: plugin.expanded, has_about_text: !!plugin.about}">
|
2021-02-20 05:10:47 +08:00
|
|
|
<div class="title" v-on:click="plugin.toggleInfo()">
|
2021-09-21 17:20:10 +08:00
|
|
|
<div class="icon_wrapper plugin_icon normal" v-html="getIconNode(plugin.icon || 'error_outline', plugin.icon ? plugin.color : 'var(--color-close)').outerHTML"></div>
|
2021-02-20 05:10:47 +08:00
|
|
|
|
|
|
|
<i v-if="plugin.expanded" class="material-icons plugin_expand_icon">expand_less</i>
|
|
|
|
<i v-else class="material-icons plugin_expand_icon">expand_more</i>
|
2021-08-14 15:48:06 +08:00
|
|
|
{{ plugin.title || plugin.id }}
|
2021-02-20 05:10:47 +08:00
|
|
|
</div>
|
2021-08-07 21:13:20 +08:00
|
|
|
<div class="plugin_version">{{ plugin.version }}</div>
|
2021-02-20 05:10:47 +08:00
|
|
|
<div class="button_bar" v-if="plugin.installed || plugin.isInstallable() == true">
|
|
|
|
<button type="button" class="" v-on:click="plugin.uninstall()" v-if="plugin.installed"><i class="material-icons">delete</i><span class="tl">${tl('dialog.plugins.uninstall')}</span></button>
|
|
|
|
<button type="button" class="" v-on:click="plugin.download(true)" v-else><i class="material-icons">add</i><span class="tl">${tl('dialog.plugins.install')}</span></button>
|
|
|
|
<button type="button" v-on:click="plugin.reload()" v-if="plugin.installed && plugin.isReloadable()"><i class="material-icons">refresh</i><span class="tl">${tl('dialog.plugins.reload')}</span></button>
|
|
|
|
</div>
|
|
|
|
<div class="button_bar tiny" v-if="plugin.isInstallable() != true">{{ plugin.isInstallable() }}</div>
|
|
|
|
|
|
|
|
<div class="author">{{ tl('dialog.plugins.author', [plugin.author]) }}</div>
|
|
|
|
<div class="description">{{ plugin.description }}</div>
|
|
|
|
<div v-if="plugin.expanded" class="about" v-html="marked(plugin.about)"><button>a</button></div>
|
|
|
|
<div v-if="plugin.expanded" v-on:click="plugin.toggleInfo()" style="text-decoration: underline;">${tl('dialog.plugins.show_less')}</div>
|
2021-05-25 01:45:40 +08:00
|
|
|
<ul class="plugin_tag_list">
|
2022-01-26 22:51:08 +08:00
|
|
|
<li v-for="tag in plugin.tags" :class="getTagClass(tag)" :key="tag" @click="search_term = tag;">{{tag}}</li>
|
2021-05-25 01:45:40 +08:00
|
|
|
</ul>
|
2021-02-20 05:10:47 +08:00
|
|
|
</li>
|
2021-02-24 04:56:36 +08:00
|
|
|
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && tab === 'installed'">${tl('dialog.plugins.none_installed')}</div>
|
2021-12-15 05:51:21 +08:00
|
|
|
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && tab === 'available'" id="plugin_available_empty">{{ tl(navigator.onLine ? 'dialog.plugins.none_available' : 'dialog.plugins.offline') }}</div>
|
2021-02-20 05:10:47 +08:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
`
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-08-18 00:26:14 +08:00
|
|
|
new Action('plugins_window', {
|
2018-12-27 21:03:04 +08:00
|
|
|
icon: 'extension',
|
|
|
|
category: 'blockbench',
|
|
|
|
click: function () {
|
2021-02-20 05:10:47 +08:00
|
|
|
Plugins.dialog.show();
|
2021-02-24 04:56:36 +08:00
|
|
|
let none_installed = !Plugins.all.find(plugin => plugin.installed);
|
|
|
|
if (none_installed) Plugins.dialog.content_vue.tab = 'available';
|
2021-02-20 05:10:47 +08:00
|
|
|
if (!Plugins.dialog.button_bar) {
|
|
|
|
Plugins.dialog.button_bar = $(`<div class="bar next_to_title" id="plugins_header_bar"></div>`)[0];
|
|
|
|
Plugins.dialog.object.firstElementChild.after(Plugins.dialog.button_bar);
|
|
|
|
BarItems.load_plugin.toElement('#plugins_header_bar');
|
|
|
|
BarItems.load_plugin_from_url.toElement('#plugins_header_bar');
|
|
|
|
}
|
2021-01-31 07:12:53 +08:00
|
|
|
$('#plugin_list').css('max-height', limitNumber(window.innerHeight-300, 80, 600)+'px');
|
2021-02-20 20:21:11 +08:00
|
|
|
$('dialog#plugins #plugin_search_bar input').trigger('focus')
|
2018-12-27 21:03:04 +08:00
|
|
|
}
|
|
|
|
})
|
2019-08-18 00:26:14 +08:00
|
|
|
new Action('reload_plugins', {
|
2019-02-04 04:09:35 +08:00
|
|
|
icon: 'sync',
|
|
|
|
category: 'blockbench',
|
|
|
|
click: function () {
|
|
|
|
Plugins.devReload()
|
|
|
|
}
|
|
|
|
})
|
2019-08-18 00:26:14 +08:00
|
|
|
new Action('load_plugin', {
|
2019-07-18 00:02:07 +08:00
|
|
|
icon: 'fa-file-code',
|
2018-11-12 04:19:08 +08:00
|
|
|
category: 'blockbench',
|
|
|
|
click: function () {
|
|
|
|
Blockbench.import({
|
2020-04-26 02:25:07 +08:00
|
|
|
resource_id: 'dev_plugin',
|
2019-02-04 04:09:35 +08:00
|
|
|
extensions: ['js'],
|
2018-11-12 04:19:08 +08:00
|
|
|
type: 'Blockbench Plugin',
|
|
|
|
}, function(files) {
|
2020-04-26 02:25:07 +08:00
|
|
|
new Plugin().loadFromFile(files[0], true)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
new Action('load_plugin_from_url', {
|
|
|
|
icon: 'cloud_download',
|
|
|
|
category: 'blockbench',
|
|
|
|
click: function () {
|
|
|
|
Blockbench.textPrompt('URL', '', url => {
|
|
|
|
new Plugin().loadFromURL(url, true)
|
2018-11-12 04:19:08 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2021-09-08 00:53:11 +08:00
|
|
|
new Action('add_plugin', {
|
|
|
|
icon: 'add',
|
|
|
|
category: 'blockbench',
|
|
|
|
click: function () {
|
|
|
|
setTimeout(_ => ActionControl.select('+plugin: '), 1);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
new Action('remove_plugin', {
|
|
|
|
icon: 'remove',
|
|
|
|
category: 'blockbench',
|
|
|
|
click: function () {
|
|
|
|
setTimeout(_ => ActionControl.select('-plugin: '), 1);
|
|
|
|
}
|
|
|
|
})
|
2018-11-12 04:19:08 +08:00
|
|
|
})
|