docs: Expose the rest of the core js to doxygen.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 31m35s
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 31m35s
This commit is contained in:
4
Doxyfile
4
Doxyfile
@@ -945,13 +945,13 @@ WARN_LOGFILE =
|
|||||||
|
|
||||||
INPUT = README.md \
|
INPUT = README.md \
|
||||||
core/app.js \
|
core/app.js \
|
||||||
|
core/client.js \
|
||||||
core/core.js \
|
core/core.js \
|
||||||
core/http.js \
|
core/http.js \
|
||||||
|
core/tfrpc.js \
|
||||||
docs/ \
|
docs/ \
|
||||||
src/
|
src/
|
||||||
|
|
||||||
# Not yet: core/tfrpc.js core/client.js
|
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||||
|
285
core/client.js
285
core/client.js
@@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* \defgroup tfclient Tilde Friends Client JS
|
||||||
|
* Tilde Friends client-side browser JavaScript.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \cond */
|
||||||
import {LitElement, html, css, svg} from '/lit/lit-all.min.js';
|
import {LitElement, html, css, svg} from '/lit/lit-all.min.js';
|
||||||
|
|
||||||
let cm6;
|
let cm6;
|
||||||
@@ -13,8 +21,9 @@ let gUnloading;
|
|||||||
let kErrorColor = '#dc322f';
|
let kErrorColor = '#dc322f';
|
||||||
let kDisconnectColor = '#f00';
|
let kDisconnectColor = '#f00';
|
||||||
let kStatusColor = '#fff';
|
let kStatusColor = '#fff';
|
||||||
|
/** \endcond */
|
||||||
|
|
||||||
// Functions that server-side app code can call through the app object.
|
/** Functions that server-side app code can call through the app object. */
|
||||||
const k_api = {
|
const k_api = {
|
||||||
setDocument: {args: ['content'], func: api_setDocument},
|
setDocument: {args: ['content'], func: api_setDocument},
|
||||||
postMessage: {args: ['message'], func: api_postMessage},
|
postMessage: {args: ['message'], func: api_postMessage},
|
||||||
@@ -26,29 +35,14 @@ const k_api = {
|
|||||||
setHash: {args: ['hash'], func: api_setHash},
|
setHash: {args: ['hash'], func: api_setHash},
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(tasiaiso): this is only used once, move it down ?
|
|
||||||
const k_global_style = css`
|
|
||||||
a:link {
|
|
||||||
color: #268bd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: #6c71c4;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #859900;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:active {
|
|
||||||
color: #2aa198;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that represents the top bar
|
* Class that represents the top bar
|
||||||
*/
|
*/
|
||||||
class TfNavigationElement extends LitElement {
|
class TfNavigationElement extends LitElement {
|
||||||
|
/**
|
||||||
|
* Get Lit Html properties.
|
||||||
|
* @return The properties.
|
||||||
|
*/
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
credentials: {type: Object},
|
credentials: {type: Object},
|
||||||
@@ -64,6 +58,9 @@ class TfNavigationElement extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TfNavigationElement instance.
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.permissions = {};
|
this.permissions = {};
|
||||||
@@ -76,7 +73,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} event
|
* @param event The HTML event.
|
||||||
*/
|
*/
|
||||||
toggle_edit(event) {
|
toggle_edit(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -89,7 +86,7 @@ class TfNavigationElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} key
|
* @param key The permission to reset.
|
||||||
*/
|
*/
|
||||||
reset_permission(key) {
|
reset_permission(key) {
|
||||||
send({action: 'resetPermission', permission: key});
|
send({action: 'resetPermission', permission: key});
|
||||||
@@ -97,9 +94,9 @@ class TfNavigationElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} key
|
* @param key The spark line identifier.
|
||||||
* @param {*} options
|
* @param options Spark line options.
|
||||||
* @returns
|
* @return A spark line HTML element.
|
||||||
*/
|
*/
|
||||||
get_spark_line(key, options) {
|
get_spark_line(key, options) {
|
||||||
if (!this.spark_lines[key]) {
|
if (!this.spark_lines[key]) {
|
||||||
@@ -118,29 +115,49 @@ class TfNavigationElement extends LitElement {
|
|||||||
return this.spark_lines[key];
|
return this.spark_lines[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the active SSB identity for the current application.
|
||||||
|
* @param id The identity.
|
||||||
|
*/
|
||||||
set_active_identity(id) {
|
set_active_identity(id) {
|
||||||
send({action: 'setActiveIdentity', identity: id});
|
send({action: 'setActiveIdentity', identity: id});
|
||||||
this.renderRoot.getElementById('id_dropdown').classList.remove('w3-show');
|
this.renderRoot.getElementById('id_dropdown').classList.remove('w3-show');
|
||||||
}
|
}
|
||||||
|
|
||||||
create_identity(event) {
|
/**
|
||||||
|
* Create a new SSB identity.
|
||||||
|
*/
|
||||||
|
create_identity() {
|
||||||
if (confirm('Are you sure you want to create a new identity?')) {
|
if (confirm('Are you sure you want to create a new identity?')) {
|
||||||
send({action: 'createIdentity'});
|
send({action: 'createIdentity'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle visibility of the ID dropdown.
|
||||||
|
*/
|
||||||
toggle_id_dropdown() {
|
toggle_id_dropdown() {
|
||||||
this.renderRoot.getElementById('id_dropdown').classList.toggle('w3-show');
|
this.renderRoot.getElementById('id_dropdown').classList.toggle('w3-show');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit the current identity's SSB profile.
|
||||||
|
*/
|
||||||
edit_profile() {
|
edit_profile() {
|
||||||
window.location.href = '/~core/ssb/#' + this.identity;
|
window.location.href = '/~core/ssb/#' + this.identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign out of the current Tilde Friends user.
|
||||||
|
*/
|
||||||
logout() {
|
logout() {
|
||||||
window.location.href = `/login/logout?return=${encodeURIComponent(url() + hash())}`;
|
window.location.href = `/login/logout?return=${encodeURIComponent(url() + hash())}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the identity dropdown.
|
||||||
|
* @return Lit HTML.
|
||||||
|
*/
|
||||||
render_identity() {
|
render_identity() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
@@ -287,6 +304,9 @@ class TfNavigationElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the current error.
|
||||||
|
*/
|
||||||
clear_error() {
|
clear_error() {
|
||||||
this.status = {};
|
this.status = {};
|
||||||
}
|
}
|
||||||
@@ -297,6 +317,23 @@ class TfNavigationElement extends LitElement {
|
|||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
const k_global_style = css`
|
||||||
|
a:link {
|
||||||
|
color: #268bd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: #6c71c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #859900;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:active {
|
||||||
|
color: #2aa198;
|
||||||
|
}
|
||||||
|
`;
|
||||||
return html`
|
return html`
|
||||||
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
|
||||||
<style>
|
<style>
|
||||||
@@ -407,6 +444,10 @@ customElements.define('tf-navigation', TfNavigationElement);
|
|||||||
* TODOC
|
* TODOC
|
||||||
*/
|
*/
|
||||||
class TfFilesElement extends LitElement {
|
class TfFilesElement extends LitElement {
|
||||||
|
/**
|
||||||
|
* LitElement properties.
|
||||||
|
* @return The properties.
|
||||||
|
*/
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
current: {type: String},
|
current: {type: String},
|
||||||
@@ -416,6 +457,9 @@ class TfFilesElement extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TfFilesElement instance.
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.files = {};
|
this.files = {};
|
||||||
@@ -424,7 +468,7 @@ class TfFilesElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} file
|
* @param file The file.
|
||||||
*/
|
*/
|
||||||
file_click(file) {
|
file_click(file) {
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
@@ -440,8 +484,8 @@ class TfFilesElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} file
|
* @param file The file.
|
||||||
* @returns
|
* @returns Lit HTML.
|
||||||
*/
|
*/
|
||||||
render_file(file) {
|
render_file(file) {
|
||||||
let classes = ['file'];
|
let classes = ['file'];
|
||||||
@@ -464,7 +508,7 @@ class TfFilesElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} event
|
* @param event The event.
|
||||||
*/
|
*/
|
||||||
async drop(event) {
|
async drop(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -490,7 +534,7 @@ class TfFilesElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} event
|
* @param event The event.
|
||||||
*/
|
*/
|
||||||
drag_enter(event) {
|
drag_enter(event) {
|
||||||
this.dropping++;
|
this.dropping++;
|
||||||
@@ -500,7 +544,7 @@ class TfFilesElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} event
|
* @param event The event.
|
||||||
*/
|
*/
|
||||||
drag_leave(event) {
|
drag_leave(event) {
|
||||||
this.dropping--;
|
this.dropping--;
|
||||||
@@ -509,6 +553,10 @@ class TfFilesElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drag over event.
|
||||||
|
* @param event The event.
|
||||||
|
*/
|
||||||
drag_over(event) {
|
drag_over(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
@@ -565,6 +613,10 @@ customElements.define('tf-files', TfFilesElement);
|
|||||||
* TODOC
|
* TODOC
|
||||||
*/
|
*/
|
||||||
class TfFilesPaneElement extends LitElement {
|
class TfFilesPaneElement extends LitElement {
|
||||||
|
/**
|
||||||
|
* Get Lit Html properties.
|
||||||
|
* @return The properties.
|
||||||
|
*/
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
expanded: {type: Boolean},
|
expanded: {type: Boolean},
|
||||||
@@ -573,6 +625,9 @@ class TfFilesPaneElement extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TfFilesPaneElement instance.
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.expanded = window.localStorage.getItem('files') != '0';
|
this.expanded = window.localStorage.getItem('files') != '0';
|
||||||
@@ -581,7 +636,7 @@ class TfFilesPaneElement extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} expanded
|
* @param expanded Whether the files pane is expanded.
|
||||||
*/
|
*/
|
||||||
set_expanded(expanded) {
|
set_expanded(expanded) {
|
||||||
this.expanded = expanded;
|
this.expanded = expanded;
|
||||||
@@ -760,10 +815,9 @@ window.addEventListener('keydown', function (event) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Make sure a set of dependencies are loaded
|
||||||
* @param {*} nodes
|
* @param nodes An array of descriptions of dependencies to load.
|
||||||
* @param {*} callback
|
* @param callback Called when all dependencies are loaded.
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
function ensureLoaded(nodes, callback) {
|
function ensureLoaded(nodes, callback) {
|
||||||
if (!nodes.length) {
|
if (!nodes.length) {
|
||||||
@@ -857,23 +911,10 @@ function trace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Load a single file.
|
||||||
* @param {*} name
|
* @param name The name by which the file is known.
|
||||||
* @returns
|
* @param id The file's ID.
|
||||||
*/
|
* @return A promise resolved with the file's contents.
|
||||||
function guessMode(name) {
|
|
||||||
return name.endsWith('.js')
|
|
||||||
? 'javascript'
|
|
||||||
: name.endsWith('.html')
|
|
||||||
? 'htmlmixed'
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODOC
|
|
||||||
* @param {*} name
|
|
||||||
* @param {*} id
|
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
function loadFile(name, id) {
|
function loadFile(name, id) {
|
||||||
return fetch('/' + id + '/view')
|
return fetch('/' + id + '/view')
|
||||||
@@ -899,9 +940,9 @@ function loadFile(name, id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Load files for the app.
|
||||||
* @param {*} path
|
* @param path The app path to load.
|
||||||
* @returns
|
* @return A promise resolved when the app is laoded.
|
||||||
*/
|
*/
|
||||||
async function load(path) {
|
async function load(path) {
|
||||||
let response = await fetch((path || url()) + 'view');
|
let response = await fetch((path || url()) + 'view');
|
||||||
@@ -958,9 +999,9 @@ function explodePath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Save the app.
|
||||||
* @param {*} save_to
|
* @param save_to An optional path to which to save the app.
|
||||||
* @returns
|
* @return A promise resoled when the app is saved.
|
||||||
*/
|
*/
|
||||||
function save(save_to) {
|
function save(save_to) {
|
||||||
document.getElementById('save').disabled = true;
|
document.getElementById('save').disabled = true;
|
||||||
@@ -1129,8 +1170,8 @@ function hash() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Set the iframe document contents.
|
||||||
* @param {*} content
|
* @param content The contents.
|
||||||
*/
|
*/
|
||||||
function api_setDocument(content) {
|
function api_setDocument(content) {
|
||||||
let iframe = document.getElementById('document');
|
let iframe = document.getElementById('document');
|
||||||
@@ -1138,8 +1179,8 @@ function api_setDocument(content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Send a message to the sandboxed iframe.
|
||||||
* @param {*} message
|
* @param message The message.
|
||||||
*/
|
*/
|
||||||
function api_postMessage(message) {
|
function api_postMessage(message) {
|
||||||
let iframe = document.getElementById('document');
|
let iframe = document.getElementById('document');
|
||||||
@@ -1148,7 +1189,7 @@ function api_postMessage(message) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} error
|
* @param error The error.
|
||||||
*/
|
*/
|
||||||
function api_error(error) {
|
function api_error(error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -1162,28 +1203,28 @@ function api_error(error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
et a value in local storage.
|
||||||
* @param {*} key
|
* @param key The key.
|
||||||
* @param {*} value
|
* @param value The value.
|
||||||
*/
|
*/
|
||||||
function api_localStorageSet(key, value) {
|
function api_localStorageSet(key, value) {
|
||||||
window.localStorage.setItem('app:' + key, value);
|
window.localStorage.setItem('app:' + key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Get a value from local storage.
|
||||||
* @param {*} key
|
* @param key The key.
|
||||||
* @returns
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
function api_localStorageGet(key) {
|
function api_localStorageGet(key) {
|
||||||
return window.localStorage.getItem('app:' + key);
|
return window.localStorage.getItem('app:' + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Request a permission
|
||||||
* @param {*} permission
|
* @param permission The permission to request.
|
||||||
* @param {*} id
|
* @param id The id requeesting the permission.
|
||||||
* @returns
|
* @return A promise fulfilled if the permission was granted.
|
||||||
*/
|
*/
|
||||||
function api_requestPermission(permission, id) {
|
function api_requestPermission(permission, id) {
|
||||||
let outer = document.createElement('div');
|
let outer = document.createElement('div');
|
||||||
@@ -1259,8 +1300,8 @@ function api_print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Set the window's location hash.
|
||||||
* @param {*} hash
|
* @param hash The new hash.
|
||||||
*/
|
*/
|
||||||
function api_setHash(hash) {
|
function api_setHash(hash) {
|
||||||
window.location.hash = hash;
|
window.location.hash = hash;
|
||||||
@@ -1268,7 +1309,7 @@ function api_setHash(hash) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} message
|
* @param message The message.
|
||||||
*/
|
*/
|
||||||
function _receive_websocket_message(message) {
|
function _receive_websocket_message(message) {
|
||||||
if (message && message.action == 'session') {
|
if (message && message.action == 'session') {
|
||||||
@@ -1364,9 +1405,9 @@ function _receive_websocket_message(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Set the status message.
|
||||||
* @param {*} message
|
* @param message The message.
|
||||||
* @param {*} color
|
* @param color The message's color.
|
||||||
*/
|
*/
|
||||||
function setStatusMessage(message, color) {
|
function setStatusMessage(message, color) {
|
||||||
document.getElementsByTagName('tf-navigation')[0].status = {
|
document.getElementsByTagName('tf-navigation')[0].status = {
|
||||||
@@ -1377,8 +1418,8 @@ function setStatusMessage(message, color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Send a message to the app.
|
||||||
* @param {*} value
|
* @param value The message.
|
||||||
*/
|
*/
|
||||||
function send(value) {
|
function send(value) {
|
||||||
try {
|
try {
|
||||||
@@ -1390,49 +1431,6 @@ function send(value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODOC
|
|
||||||
* @param {*} sourceData
|
|
||||||
* @param {*} maxWidth
|
|
||||||
* @param {*} maxHeight
|
|
||||||
* @param {*} callback
|
|
||||||
*/
|
|
||||||
function fixImage(sourceData, maxWidth, maxHeight, callback) {
|
|
||||||
let result = sourceData;
|
|
||||||
let image = new Image();
|
|
||||||
image.crossOrigin = 'anonymous';
|
|
||||||
image.referrerPolicy = 'no-referrer';
|
|
||||||
image.onload = function () {
|
|
||||||
if (image.width > maxWidth || image.height > maxHeight) {
|
|
||||||
let downScale = Math.min(
|
|
||||||
maxWidth / image.width,
|
|
||||||
maxHeight / image.height
|
|
||||||
);
|
|
||||||
let canvas = document.createElement('canvas');
|
|
||||||
canvas.width = image.width * downScale;
|
|
||||||
canvas.height = image.height * downScale;
|
|
||||||
let context = canvas.getContext('2d');
|
|
||||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
image.width = canvas.width;
|
|
||||||
image.height = canvas.height;
|
|
||||||
context.drawImage(image, 0, 0, image.width, image.height);
|
|
||||||
result = canvas.toDataURL();
|
|
||||||
}
|
|
||||||
callback(result);
|
|
||||||
};
|
|
||||||
image.src = sourceData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODOC
|
|
||||||
* @param {*} image
|
|
||||||
*/
|
|
||||||
function sendImage(image) {
|
|
||||||
fixImage(image, 320, 240, function (result) {
|
|
||||||
send({image: result});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* TODOC
|
||||||
*/
|
*/
|
||||||
@@ -1461,8 +1459,8 @@ function blur() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Handle a message.
|
||||||
* @param {*} event
|
* @param event The message.
|
||||||
*/
|
*/
|
||||||
function message(event) {
|
function message(event) {
|
||||||
if (
|
if (
|
||||||
@@ -1510,8 +1508,8 @@ function message(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Reconnect the WebSocket.
|
||||||
* @param {*} path
|
* @param path The path to which the WebSocket should be connected.
|
||||||
*/
|
*/
|
||||||
function reconnect(path) {
|
function reconnect(path) {
|
||||||
let oldSocket = gSocket;
|
let oldSocket = gSocket;
|
||||||
@@ -1526,8 +1524,8 @@ function reconnect(path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Connect the WebSocket.
|
||||||
* @param {*} path
|
* @param path The path to which to connect.
|
||||||
*/
|
*/
|
||||||
function connectSocket(path) {
|
function connectSocket(path) {
|
||||||
if (!gSocket || gSocket.readyState != gSocket.OPEN) {
|
if (!gSocket || gSocket.readyState != gSocket.OPEN) {
|
||||||
@@ -1593,8 +1591,8 @@ function connectSocket(path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Open a file by name.
|
||||||
* @param {*} name
|
* @param name The file to open.
|
||||||
*/
|
*/
|
||||||
function openFile(name) {
|
function openFile(name) {
|
||||||
let newDoc =
|
let newDoc =
|
||||||
@@ -1641,8 +1639,8 @@ function updateFiles() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Create a new file with the given name.
|
||||||
* @param {*} name
|
* @param name The file's name.
|
||||||
*/
|
*/
|
||||||
function makeNewFile(name) {
|
function makeNewFile(name) {
|
||||||
gFiles[name] = {
|
gFiles[name] = {
|
||||||
@@ -1703,10 +1701,10 @@ async function appExport() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Save a file.
|
||||||
* @param {*} name
|
* @param name The file to svae.
|
||||||
* @param {*} file
|
* @param file The file contents.
|
||||||
* @returns
|
* @return A promise resolved with the blob ID of the saved file.
|
||||||
*/
|
*/
|
||||||
async function save_file_to_blob_id(name, file) {
|
async function save_file_to_blob_id(name, file) {
|
||||||
console.log(`Saving ${name}.`);
|
console.log(`Saving ${name}.`);
|
||||||
@@ -1801,7 +1799,7 @@ async function appImport() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Prettify the current source file.
|
||||||
*/
|
*/
|
||||||
async function sourcePretty() {
|
async function sourcePretty() {
|
||||||
let prettier = (await import('/prettier/standalone.mjs')).default;
|
let prettier = (await import('/prettier/standalone.mjs')).default;
|
||||||
@@ -1829,6 +1827,9 @@ async function sourcePretty() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle visible whitespace.
|
||||||
|
*/
|
||||||
function toggleVisibleWhitespace() {
|
function toggleVisibleWhitespace() {
|
||||||
let editor_style = document.getElementById('editor_style');
|
let editor_style = document.getElementById('editor_style');
|
||||||
/*
|
/*
|
||||||
@@ -1902,3 +1903,5 @@ window.addEventListener('load', function () {
|
|||||||
toggleVisibleWhitespace();
|
toggleVisibleWhitespace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
125
core/core.js
125
core/core.js
@@ -1,12 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
** \defgroup tfcore Tilde Friends Core JS
|
* \file
|
||||||
** Tilde Friends process management, in JavaScript.
|
* \defgroup tfcore Tilde Friends Core JS
|
||||||
** @{
|
* Tilde Friends process management, in JavaScript.
|
||||||
*/
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \cond */
|
||||||
import * as app from './app.js';
|
import * as app from './app.js';
|
||||||
import * as http from './http.js';
|
import * as http from './http.js';
|
||||||
|
|
||||||
|
export {invoke, getProcessBlob};
|
||||||
|
/** \endcond */
|
||||||
|
|
||||||
/** All running processes. */
|
/** All running processes. */
|
||||||
let gProcesses = {};
|
let gProcesses = {};
|
||||||
/** Whether stats are currently being sent. */
|
/** Whether stats are currently being sent. */
|
||||||
@@ -17,9 +22,9 @@ let g_handler_index = 0;
|
|||||||
const k_ping_interval = 60 * 1000;
|
const k_ping_interval = 60 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Print an error.
|
* Print an error.
|
||||||
** @param error The error.
|
* @param error The error.
|
||||||
*/
|
*/
|
||||||
function printError(error) {
|
function printError(error) {
|
||||||
if (error.stackTrace) {
|
if (error.stackTrace) {
|
||||||
print(error.fileName + ':' + error.lineNumber + ': ' + error.message);
|
print(error.fileName + ':' + error.lineNumber + ': ' + error.message);
|
||||||
@@ -33,11 +38,11 @@ function printError(error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Invoke a handler.
|
* Invoke a handler.
|
||||||
** @param handlers The handlers on which to invoke the callback.
|
* @param handlers The handlers on which to invoke the callback.
|
||||||
** @param argv Arguments to pass to the handlers.
|
* @param argv Arguments to pass to the handlers.
|
||||||
** @return A promise.
|
* @return A promise.
|
||||||
*/
|
*/
|
||||||
function invoke(handlers, argv) {
|
function invoke(handlers, argv) {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
if (handlers) {
|
if (handlers) {
|
||||||
@@ -59,11 +64,11 @@ function invoke(handlers, argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Broadcast a named event to all registered apps.
|
* Broadcast a named event to all registered apps.
|
||||||
** @param eventName the name of the event.
|
* @param eventName the name of the event.
|
||||||
** @param argv Arguments to pass to the handlers.
|
* @param argv Arguments to pass to the handlers.
|
||||||
** @return A promise.
|
* @return A promise.
|
||||||
*/
|
*/
|
||||||
function broadcastEvent(eventName, argv) {
|
function broadcastEvent(eventName, argv) {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
for (let process of Object.values(gProcesses)) {
|
for (let process of Object.values(gProcesses)) {
|
||||||
@@ -75,10 +80,10 @@ function broadcastEvent(eventName, argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Send a message to all other instances of the same app.
|
* Send a message to all other instances of the same app.
|
||||||
** @param message The message.
|
* @param message The message.
|
||||||
** @return A promise.
|
* @return A promise.
|
||||||
*/
|
*/
|
||||||
function broadcast(message) {
|
function broadcast(message) {
|
||||||
let sender = this;
|
let sender = this;
|
||||||
let promises = [];
|
let promises = [];
|
||||||
@@ -96,14 +101,14 @@ function broadcast(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Send a message to all instances of the same app running as the same user.
|
* Send a message to all instances of the same app running as the same user.
|
||||||
** @param user The user.
|
* @param user The user.
|
||||||
** @param packageOwner The owner of the app.
|
* @param packageOwner The owner of the app.
|
||||||
** @param packageName The name of the app.
|
* @param packageName The name of the app.
|
||||||
** @param eventName The name of the event.
|
* @param eventName The name of the event.
|
||||||
** @param argv The arguments to pass.
|
* @param argv The arguments to pass.
|
||||||
** @return A promise.
|
* @return A promise.
|
||||||
*/
|
*/
|
||||||
function broadcastAppEventToUser(
|
function broadcastAppEventToUser(
|
||||||
user,
|
user,
|
||||||
packageOwner,
|
packageOwner,
|
||||||
@@ -127,10 +132,10 @@ function broadcastAppEventToUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Get user context information for a call.
|
* Get user context information for a call.
|
||||||
** @param caller The calling process.
|
* @param caller The calling process.
|
||||||
** @param process The receiving process.
|
* @param process The receiving process.
|
||||||
*/
|
*/
|
||||||
function getUser(caller, process) {
|
function getUser(caller, process) {
|
||||||
return {
|
return {
|
||||||
key: process.key,
|
key: process.key,
|
||||||
@@ -142,12 +147,12 @@ function getUser(caller, process) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Send a message.
|
* Send a message.
|
||||||
** @param from The calling process.
|
* @param from The calling process.
|
||||||
** @param to The receiving process.
|
* @param to The receiving process.
|
||||||
** @param message The message.
|
* @param message The message.
|
||||||
** @return A promise.
|
* @return A promise.
|
||||||
*/
|
*/
|
||||||
function postMessageInternal(from, to, message) {
|
function postMessageInternal(from, to, message) {
|
||||||
if (to.eventHandlers['message']) {
|
if (to.eventHandlers['message']) {
|
||||||
return invoke(to.eventHandlers['message'], [getUser(from, from), message]);
|
return invoke(to.eventHandlers['message'], [getUser(from, from), message]);
|
||||||
@@ -155,12 +160,12 @@ function postMessageInternal(from, to, message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Get or create a process for an app blob.
|
* Get or create a process for an app blob.
|
||||||
** @param blobId The blob identifier.
|
* @param blobId The blob identifier.
|
||||||
** @param key A unique key for the invocation.
|
* @param key A unique key for the invocation.
|
||||||
** @param options Other options.
|
* @param options Other options.
|
||||||
** @return The process.
|
* @return The process.
|
||||||
*/
|
*/
|
||||||
async function getProcessBlob(blobId, key, options) {
|
async function getProcessBlob(blobId, key, options) {
|
||||||
let process = gProcesses[key];
|
let process = gProcesses[key];
|
||||||
if (!process && !(options && 'create' in options && !options.create)) {
|
if (!process && !(options && 'create' in options && !options.create)) {
|
||||||
@@ -711,9 +716,9 @@ ssb.addEventListener('connections', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Load settings from the database.
|
* Load settings from the database.
|
||||||
** @return The settings as a key value pairs object.
|
* @return The settings as a key value pairs object.
|
||||||
*/
|
*/
|
||||||
async function loadSettings() {
|
async function loadSettings() {
|
||||||
let data = {};
|
let data = {};
|
||||||
try {
|
try {
|
||||||
@@ -733,8 +738,8 @@ async function loadSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Send periodic stats to all clients.
|
* Send periodic stats to all clients.
|
||||||
*/
|
*/
|
||||||
function sendStats() {
|
function sendStats() {
|
||||||
let apps = Object.values(gProcesses)
|
let apps = Object.values(gProcesses)
|
||||||
.filter((process) => process.app)
|
.filter((process) => process.app)
|
||||||
@@ -751,15 +756,15 @@ function sendStats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Invoke an app's handler.js.
|
* Invoke an app's handler.js.
|
||||||
** @param response The response object.
|
* @param response The response object.
|
||||||
** @param app_blob_id The app's blob identifier.
|
* @param app_blob_id The app's blob identifier.
|
||||||
** @param path The request path.
|
* @param path The request path.
|
||||||
** @param query The request query string.
|
* @param query The request query string.
|
||||||
** @param headers The request headers.
|
* @param headers The request headers.
|
||||||
** @param package_owner The app's owner.
|
* @param package_owner The app's owner.
|
||||||
** @param package_name The app's name.
|
* @param package_name The app's name.
|
||||||
*/
|
*/
|
||||||
exports.callAppHandler = async function callAppHandler(
|
exports.callAppHandler = async function callAppHandler(
|
||||||
response,
|
response,
|
||||||
app_blob_id,
|
app_blob_id,
|
||||||
@@ -826,5 +831,3 @@ exports.callAppHandler = async function callAppHandler(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
export { invoke, getProcessBlob };
|
|
||||||
|
@@ -1,6 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* \defgroup tfrpc Tilde Friends RPC.
|
||||||
|
* Tilde Friends RPC.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Whether this module is being run in a web browser. */
|
||||||
const k_is_browser = get_is_browser();
|
const k_is_browser = get_is_browser();
|
||||||
|
/** Registered methods. */
|
||||||
let g_api = {};
|
let g_api = {};
|
||||||
|
/** The next method identifier. */
|
||||||
let g_next_id = 1;
|
let g_next_id = 1;
|
||||||
|
/** Identifiers of pending calls. */
|
||||||
let g_calls = {};
|
let g_calls = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,16 +26,30 @@ function get_is_browser() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \cond */
|
||||||
if (k_is_browser) {
|
if (k_is_browser) {
|
||||||
print = console.log;
|
print = console.log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (k_is_browser) {
|
||||||
|
window.addEventListener('message', function (event) {
|
||||||
|
call_rpc(event.data);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
core.register('message', function (message) {
|
||||||
|
call_rpc(message?.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export let rpc = new Proxy({}, {get: make_rpc});
|
||||||
|
/** \endcond */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Make a function to invoke a remote procedure.
|
||||||
* @param {*} target
|
* @param target The target.
|
||||||
* @param {*} prop
|
* @param prop The name of the function.
|
||||||
* @param {*} receiver
|
* @param receiver The receiver.
|
||||||
* @returns
|
* @return A function.
|
||||||
*/
|
*/
|
||||||
function make_rpc(target, prop, receiver) {
|
function make_rpc(target, prop, receiver) {
|
||||||
return function () {
|
return function () {
|
||||||
@@ -55,8 +80,8 @@ function make_rpc(target, prop, receiver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Send a response.
|
||||||
* @param {*} response
|
* @param response The response.
|
||||||
*/
|
*/
|
||||||
function send(response) {
|
function send(response) {
|
||||||
if (k_is_browser) {
|
if (k_is_browser) {
|
||||||
@@ -67,8 +92,8 @@ function send(response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Invoke a remote procedure.
|
||||||
* @param {*} message
|
* @param message An object describing the call.
|
||||||
*/
|
*/
|
||||||
function call_rpc(message) {
|
function call_rpc(message) {
|
||||||
if (message && message.message === 'tfrpc') {
|
if (message && message.message === 'tfrpc') {
|
||||||
@@ -112,22 +137,12 @@ function call_rpc(message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k_is_browser) {
|
|
||||||
window.addEventListener('message', function (event) {
|
|
||||||
call_rpc(event.data);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
core.register('message', function (message) {
|
|
||||||
call_rpc(message?.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export let rpc = new Proxy({}, {get: make_rpc});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODOC
|
* Register a function that to be called remotely.
|
||||||
* @param {*} method
|
* @param method The method.
|
||||||
*/
|
*/
|
||||||
export function register(method) {
|
export function register(method) {
|
||||||
g_api[method.name] = method;
|
g_api[method.name] = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
Reference in New Issue
Block a user