blockbench/js/api.js

388 lines
11 KiB
JavaScript
Raw Normal View History

2021-01-24 06:24:14 +08:00
const LastVersion = localStorage.getItem('last_version') || localStorage.getItem('welcomed_version') || appVersion;
2019-07-18 00:02:07 +08:00
const Blockbench = {
isWeb: !isApp,
isMobile: (window.innerWidth <= 960 || window.innerHeight <= 500) && 'ontouchend' in document,
isLandscape: window.innerWidth > window.innerHeight,
isTouch: 'ontouchend' in document,
get isPWA() {
return navigator.standalone || window.matchMedia('(display-mode: standalone)').matches;
},
2019-07-18 00:02:07 +08:00
version: appVersion,
platform: 'web',
flags: [],
drag_handlers: {},
events: {},
openTime: new Date(),
2018-10-18 01:50:25 +08:00
edit(aspects, cb) {
Undo.initEdit(aspects)
cb()
Undo.finishEdit()
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
reload() {
if (isApp) {
Blockbench.setProgress(0)
2019-07-18 00:02:07 +08:00
Blockbench.addFlag('allow_closing')
2020-07-16 15:32:59 +08:00
Blockbench.addFlag('allow_reload')
2018-10-18 01:50:25 +08:00
currentwindow.reload()
} else {
location.reload()
}
2019-07-18 00:02:07 +08:00
},
isNewerThan(version) {
return compareVersions(Blockbench.version, version);
},
2020-10-12 01:53:22 +08:00
isOlderThan(version) {
return compareVersions(version, Blockbench.version);
},
2018-10-18 01:50:25 +08:00
registerEdit() {
2019-02-04 04:09:35 +08:00
console.warn('Blockbench.registerEdit is outdated. Please use Undo.initEdit and Undo.finishEdit')
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
//Interface
getIconNode(icon, color) {
2020-01-24 01:53:36 +08:00
let node;
2018-10-18 01:50:25 +08:00
if (typeof icon === 'function') {
icon = icon()
}
2020-01-24 01:53:36 +08:00
if (icon === undefined) {
//Missing
node = document.createElement('i');
node.classList.add('material-icons', 'notranslate', 'icon');
2020-01-24 01:53:36 +08:00
node.innerText = 'help_outline';
} else if (icon instanceof HTMLElement) {
//Node
node = icon
2022-08-15 20:57:07 +08:00
} else if (icon === true || icon === false) {
//Boolean
node = document.createElement('i');
node.classList.add('material-icons', 'notranslate', 'icon');
2022-08-15 20:57:07 +08:00
node.innerText = icon ? 'check_box' : 'check_box_outline_blank';
2020-03-05 03:56:17 +08:00
} else if (icon === null) {
//Node
node = document.createElement('i');
node.classList.add('fa_big', 'icon');
} else if (icon.match(/^(fa[.-])|(fa[rsb]\.)/)) {
2020-01-24 01:53:36 +08:00
//Font Awesome
node = document.createElement('i');
node.classList.add('fa_big', 'icon');
if (icon.substr(3, 1) === '.') {
node.classList.add(icon.substr(0, 3), icon.substr(4));
} else {
node.classList.add('fa', icon);
}
} else if (icon.substr(0, 5) === 'icon-') {
//Icomoon
node = document.createElement('i');
node.classList.add(icon, 'icon');
} else if (icon.substr(0, 14) === 'data:image/png') {
//Data URL
node = document.createElement('img');
node.classList.add('icon');
node.src = icon;
} else {
//Material Icon
node = document.createElement('i');
node.classList.add('material-icons', 'notranslate', 'icon');
2020-01-24 01:53:36 +08:00
node.innerText = icon;
}
if (color) {
if (color === 'x') {
node.classList.add('color_x');
} else if (color === 'y') {
node.classList.add('color_y');
} else if (color === 'z') {
node.classList.add('color_z');
} else if (typeof color === 'string') {
node.style.color = color;
}
}
return node
2019-07-18 00:02:07 +08:00
},
showQuickMessage(message, time = 1000) {
document.getElementById('quick_message_box')?.remove();
let quick_message_box = Interface.createElement('div', {id: 'quick_message_box'}, tl(message));
document.body.append(quick_message_box);
2018-10-18 01:50:25 +08:00
setTimeout(function() {
quick_message_box.remove()
}, time);
2019-07-18 00:02:07 +08:00
},
/**
*
* @param {object} options Options
* @param {string} options.text Text Message
* @param {string} [options.icon] Blockbench icon string
* @param {number} [options.expire] Expire time in miliseconds
* @param {string} [options.color] Background color, accepts any CSS color string
2021-05-06 03:04:16 +08:00
* @param {function} [options.click] Method to run on click. Return `true` to close toast
*
*/
showToastNotification(options) {
let notification = document.createElement('li');
notification.className = 'toast_notification';
if (options.icon) {
let icon = Blockbench.getIconNode(options.icon);
notification.append(icon);
}
let text = document.createElement('span');
text.innerText = tl(options.text);
notification.append(text);
let close_button = document.createElement('div');
close_button.innerHTML = '<i class="material-icons">clear</i>';
close_button.className = 'toast_close_button';
close_button.addEventListener('click', (event) => {
notification.remove();
})
notification.append(close_button);
if (options.color) {
notification.style.backgroundColor = options.color;
}
if (typeof options.click == 'function') {
notification.addEventListener('click', (event) => {
if (event.target == close_button || event.target.parentElement == close_button) return;
let result = options.click(event);
if (result == true) {
notification.remove();
}
})
notification.style.cursor = 'pointer';
}
if (options.expire) {
setTimeout(() => {
notification.remove();
}, options.expire);
}
document.getElementById('toast_notification_list').append(notification);
function deletableToast(node) {
this.delete = function() {
node.remove();
}
}
return new deletableToast(notification);
2019-12-16 03:04:31 +08:00
},
2023-11-05 21:22:59 +08:00
setCursorTooltip(text) {
if (!Interface.cursor_tooltip) {
Interface.cursor_tooltip = Interface.createElement('div', {id: 'cursor_tooltip'});
}
if (text) {
Interface.cursor_tooltip.textContent = text;
if (!Interface.cursor_tooltip.parentNode) {
document.body.append(Interface.cursor_tooltip);
Interface.cursor_tooltip.style.left = mouse_pos.x + 'px';
Interface.cursor_tooltip.style.top = mouse_pos.y + 'px';
}
} else {
Interface.cursor_tooltip.textContent = '';
Interface.cursor_tooltip.remove();
}
},
2018-10-18 01:50:25 +08:00
showStatusMessage(message, time) {
2018-11-12 04:19:08 +08:00
Blockbench.setStatusBarText(tl(message))
setTimeout(function() {
Blockbench.setStatusBarText()
2019-07-18 00:02:07 +08:00
}, time ? time : 800)
},
2018-11-12 04:19:08 +08:00
setStatusBarText(text) {
2020-01-24 01:53:36 +08:00
if (text !== undefined) {
2018-11-12 04:19:08 +08:00
Prop.file_name = text
} else {
Prop.file_name = Prop.file_name_alt||''
}
2019-07-18 00:02:07 +08:00
},
2018-12-27 21:03:04 +08:00
setProgress(progress, time, bar) {
setProgressBar(bar, progress||0, time)
2019-07-18 00:02:07 +08:00
},
2017-10-27 01:00:52 +08:00
showMessage(message, location) {
if (location === 'status_bar') {
2018-10-18 01:50:25 +08:00
Blockbench.showStatusMessage(message)
2017-10-27 01:00:52 +08:00
} else if (location === 'center') {
2018-10-18 01:50:25 +08:00
Blockbench.showQuickMessage(message)
2017-10-27 01:00:52 +08:00
}
2019-07-18 00:02:07 +08:00
},
showMessageBox(options = 0, cb) {
return new MessageBox(options, cb).show();
2019-07-18 00:02:07 +08:00
},
async textPrompt(title, value, callback, placeholder = null) {
let answer = await new Promise((resolve) => {
new Dialog({
id: 'text_input',
title: title || 'dialog.input.title',
form: {
text: {full_width: true, placeholder, value}
},
onConfirm({text}) {
if (callback) callback(text);
resolve(text);
},
onOpen() {
this.object.querySelector('input')?.focus();
}
}).show();
});
return answer;
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
addMenuEntry(name, icon, click) {
console.warn('Blockbench.addMenuEntry is deprecated. Please use Actions instead.')
let id = name.replace(/\s/g, '').toLowerCase();
var action = new Action(id, {icon: icon, name: name, click: click})
MenuBar.addAction(action, 'tools')
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
removeMenuEntry(name) {
let id = name.replace(/\s/g, '').toLowerCase();
MenuBar.removeAction('tools.'+id);
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
openLink(link) {
if (isApp) {
shell.openExternal(link)
} else {
window.open(link)
}
2019-07-18 00:02:07 +08:00
},
notification(title, text, icon) {
Notification.requestPermission().then(status => {
if (status == 'granted') {
let n = new Notification(title, {body: text, icon: icon||'favicon.png'})
n.onclick = function() {
if (isApp) {
currentwindow.focus();
} else {
window.focus();
}
}
}
})
},
//CSS
addCSS(css) {
let style_node = document.createElement('style');
2023-02-05 04:15:01 +08:00
style_node.type ='text/css';
style_node.appendChild(document.createTextNode(css));
document.getElementsByTagName('head')[0].appendChild(style_node);
function deletableStyle(node) {
this.delete = function() {
node.remove();
}
}
return new deletableStyle(style_node);
},
2018-10-18 01:50:25 +08:00
//Flags
addFlag(flag) {
2018-12-03 02:37:06 +08:00
this.flags[flag] = true
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
removeFlag(flag) {
2018-12-03 02:37:06 +08:00
delete this.flags[flag]
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
hasFlag(flag) {
2018-12-03 02:37:06 +08:00
return this.flags[flag]
2019-07-18 00:02:07 +08:00
},
2018-10-18 01:50:25 +08:00
//Events
2019-04-08 00:53:33 +08:00
dispatchEvent(event_name, data) {
2021-06-23 03:29:09 +08:00
let list = this.events[event_name];
2022-08-10 05:14:03 +08:00
let results;
if (list) {
results = [];
for (let i = 0; i < list.length; i++) {
if (typeof list[i] === 'function') {
let result = list[i](data);
results.push(result);
}
2017-10-27 01:00:52 +08:00
}
}
2023-04-19 00:19:56 +08:00
if (Validator.triggers.includes(event_name)) {
Validator.validate(event_name);
}
2021-06-23 03:29:09 +08:00
return results;
2019-07-18 00:02:07 +08:00
},
2019-04-08 00:53:33 +08:00
on(event_name, cb) {
2023-03-21 06:50:50 +08:00
return EventSystem.prototype.on.call(this, event_name, cb);
},
once(event_name, cb) {
return EventSystem.prototype.once.call(this, event_name, cb);
},
addListener(event_name, cb) {
return EventSystem.prototype.addListener.call(this, event_name, cb);
2019-07-18 00:02:07 +08:00
},
2017-10-27 01:00:52 +08:00
removeListener(event_name, cb) {
2023-03-21 06:50:50 +08:00
return EventSystem.prototype.removeListener.call(this, event_name, cb);
},
// Update
2021-01-24 06:24:14 +08:00
onUpdateTo(version, callback) {
if (LastVersion && compareVersions(version, LastVersion) && !Blockbench.isOlderThan(version)) {
2021-01-24 06:24:14 +08:00
callback(LastVersion);
}
}
2019-09-06 07:56:13 +08:00
};
2019-09-06 07:47:49 +08:00
(function() {
2021-01-24 06:24:14 +08:00
if (!LastVersion || LastVersion.replace(/.\d+$/, '') != appVersion.replace(/.\d+$/, '')) {
2019-09-06 07:47:49 +08:00
Blockbench.addFlag('after_update');
} else if (LastVersion != appVersion) {
Blockbench.addFlag('after_patch_update');
2019-09-06 07:47:49 +08:00
}
try {
let ui_mode = JSON.parse(localStorage.getItem('settings')).interface_mode.value;
if (ui_mode == 'desktop') Blockbench.isMobile = false;
if (ui_mode == 'mobile') Blockbench.isMobile = true;
} catch (err) {}
2019-09-06 07:47:49 +08:00
})();
2019-07-18 00:02:07 +08:00
if (isApp) {
Blockbench.platform = process.platform;
switch (Blockbench.platform) {
case 'win32': Blockbench.operating_system = 'Windows'; break;
case 'darwin': Blockbench.operating_system = 'macOS'; break;
default: Blockbench.operating_system = 'Linux'; break;
}
if (Blockbench.platform.includes('win32') === true) osfs = '\\';
2017-10-27 01:00:52 +08:00
}
2020-04-26 02:25:07 +08:00
const StateMemory = {
/**
* Initialize a memorized property
* @param {string} key
* @param {'string'|'number'|'boolean'|'object'|'array'} type
*/
2020-04-26 02:25:07 +08:00
init(key, type) {
let saved = localStorage.getItem(`StateMemory.${key}`)
if (typeof saved == 'string') {
try {
saved = JSON.parse(saved)
} catch (err) {
localStorage.clearItem(`StateMemory.${key}`)
}
}
if ( saved !== null && (typeof saved == type || (type == 'array' && saved instanceof Array)) ) {
StateMemory[key] = saved;
} else {
StateMemory[key] = (() => {switch (type) {
case 'string': return ''; break;
case 'number': return 0; break;
case 'boolean': return false; break;
case 'object': return {}; break;
case 'array': return []; break;
}})();
}
},
set(key, value) {
if (StateMemory[key] instanceof Array) {
StateMemory[key].replace(value);
} else {
StateMemory[key] = value;
}
StateMemory.save(key);
},
2020-04-26 02:25:07 +08:00
save(key) {
let serialized = JSON.stringify(StateMemory[key])
localStorage.setItem(`StateMemory.${key}`, serialized)
}
}