Add code documentation
This commit is contained in:
@ -2,19 +2,19 @@
|
||||
import { getAnalyser } from "superdough";
|
||||
import { type Editor } from "./main";
|
||||
|
||||
/**
|
||||
* Draw a circle at a specific position on the canvas.
|
||||
* @param {number} x - The x-coordinate of the circle's center.
|
||||
* @param {number} y - The y-coordinate of the circle's center.
|
||||
* @param {number} radius - The radius of the circle.
|
||||
* @param {string} color - The fill color of the circle.
|
||||
*/
|
||||
export const drawCircle = (
|
||||
/**
|
||||
* Draw a circle at a specific position on the canvas.
|
||||
* @param {number} x - The x-coordinate of the circle's center.
|
||||
* @param {number} y - The y-coordinate of the circle's center.
|
||||
* @param {number} radius - The radius of the circle.
|
||||
* @param {string} color - The fill color of the circle.
|
||||
*/
|
||||
app: Editor,
|
||||
x: number,
|
||||
y: number,
|
||||
radius: number,
|
||||
color: string,
|
||||
color: string
|
||||
): void => {
|
||||
// @ts-ignore
|
||||
const canvas: HTMLCanvasElement = app.interface.feedback;
|
||||
@ -28,15 +28,15 @@ export const drawCircle = (
|
||||
ctx.closePath();
|
||||
};
|
||||
|
||||
/**
|
||||
* Blinks a script indicator circle.
|
||||
* @param script - The type of script.
|
||||
* @param no - The shift amount multiplier.
|
||||
*/
|
||||
export const blinkScript = (
|
||||
/**
|
||||
* Blinks a script indicator circle.
|
||||
* @param script - The type of script.
|
||||
* @param no - The shift amount multiplier.
|
||||
*/
|
||||
app: Editor,
|
||||
script: "local" | "global" | "init",
|
||||
no?: number,
|
||||
no?: number
|
||||
) => {
|
||||
if (no !== undefined && no < 1 && no > 9) return;
|
||||
const blinkDuration =
|
||||
@ -55,15 +55,15 @@ export const blinkScript = (
|
||||
horizontalOffset + shift,
|
||||
app.interface.feedback.clientHeight - 15,
|
||||
8,
|
||||
"#fdba74",
|
||||
"#fdba74"
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the circle at a given shift.
|
||||
* @param shift - The pixel distance from the origin.
|
||||
*/
|
||||
const _clearBlinker = (shift: number) => {
|
||||
/**
|
||||
* Clears the circle at a given shift.
|
||||
* @param shift - The pixel distance from the origin.
|
||||
*/
|
||||
const x = 50 + shift;
|
||||
const y = app.interface.feedback.clientHeight - 15;
|
||||
const radius = 8;
|
||||
@ -91,17 +91,18 @@ export const blinkScript = (
|
||||
0,
|
||||
0,
|
||||
(app.interface.feedback as HTMLCanvasElement).width,
|
||||
(app.interface.feedback as HTMLCanvasElement).height,
|
||||
(app.interface.feedback as HTMLCanvasElement).height
|
||||
);
|
||||
}, blinkDuration);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages animation updates using requestAnimationFrame.
|
||||
* @param app - The Editor application context.
|
||||
*/
|
||||
export const scriptBlinkers = () => {
|
||||
/**
|
||||
* Manages animation updates using requestAnimationFrame.
|
||||
* @param app - The Editor application context.
|
||||
*/
|
||||
|
||||
let lastFrameTime = Date.now();
|
||||
const frameRate = 10;
|
||||
const minFrameDelay = 1000 / frameRate;
|
||||
@ -134,15 +135,16 @@ export interface OscilloscopeConfig {
|
||||
let lastZeroCrossingType: string | null = null; // 'negToPos' or 'posToNeg'
|
||||
let lastRenderTime: number = 0;
|
||||
|
||||
/**
|
||||
* Initializes and runs an oscilloscope using an AnalyzerNode.
|
||||
* @param {HTMLCanvasElement} canvas - The canvas element to draw the oscilloscope.
|
||||
* @param {OscilloscopeConfig} config - Configuration for the oscilloscope's appearance and behavior.
|
||||
*/
|
||||
export const runOscilloscope = (
|
||||
canvas: HTMLCanvasElement,
|
||||
app: Editor,
|
||||
app: Editor
|
||||
): void => {
|
||||
/**
|
||||
* Runs the oscilloscope visualization on the provided canvas element.
|
||||
*
|
||||
* @param canvas - The HTMLCanvasElement on which to render the visualization.
|
||||
* @param app - The Editor object containing the configuration for the oscilloscope.
|
||||
*/
|
||||
let config = app.osc;
|
||||
let analyzer = getAnalyser(config.fftSize);
|
||||
let dataArray = new Float32Array(analyzer.frequencyBinCount);
|
||||
@ -155,7 +157,7 @@ export const runOscilloscope = (
|
||||
width: number,
|
||||
height: number,
|
||||
offset_height: number,
|
||||
offset_width: number,
|
||||
offset_width: number
|
||||
) {
|
||||
const maxFPS = 30;
|
||||
const now = performance.now();
|
||||
@ -170,11 +172,11 @@ export const runOscilloscope = (
|
||||
|
||||
const performanceFactor = 1;
|
||||
const reducedDataSize = Math.floor(
|
||||
freqDataArray.length * performanceFactor,
|
||||
freqDataArray.length * performanceFactor
|
||||
);
|
||||
const numBars = Math.min(
|
||||
reducedDataSize,
|
||||
app.osc.orientation === "horizontal" ? width : height,
|
||||
app.osc.orientation === "horizontal" ? width : height
|
||||
);
|
||||
const barWidth =
|
||||
app.osc.orientation === "horizontal" ? width / numBars : height / numBars;
|
||||
@ -187,7 +189,7 @@ export const runOscilloscope = (
|
||||
for (let i = 0; i < numBars; i++) {
|
||||
barHeight = Math.floor(
|
||||
freqDataArray[Math.floor((i * freqDataArray.length) / numBars)] *
|
||||
((height / 256) * app.osc.size),
|
||||
((height / 256) * app.osc.size)
|
||||
);
|
||||
|
||||
if (app.osc.orientation === "horizontal") {
|
||||
@ -195,7 +197,7 @@ export const runOscilloscope = (
|
||||
x + offset_width,
|
||||
(height - barHeight) / 2 + offset_height,
|
||||
barWidth + 1,
|
||||
barHeight,
|
||||
barHeight
|
||||
);
|
||||
x += barWidth;
|
||||
} else {
|
||||
@ -203,7 +205,7 @@ export const runOscilloscope = (
|
||||
(width - barHeight) / 2 + offset_width,
|
||||
y + offset_height,
|
||||
barHeight,
|
||||
barWidth + 1,
|
||||
barWidth + 1
|
||||
);
|
||||
y += barWidth;
|
||||
}
|
||||
@ -232,12 +234,19 @@ export const runOscilloscope = (
|
||||
-OFFSET_WIDTH,
|
||||
-OFFSET_HEIGHT,
|
||||
WIDTH + 2 * OFFSET_WIDTH,
|
||||
HEIGHT + 2 * OFFSET_HEIGHT,
|
||||
HEIGHT + 2 * OFFSET_HEIGHT
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (analyzer.fftSize !== app.osc.fftSize) {
|
||||
// Disconnect and release the old analyzer if it exists
|
||||
if (analyzer) {
|
||||
analyzer.disconnect();
|
||||
analyzer = null; // Release the reference for garbage collection
|
||||
}
|
||||
|
||||
// Create a new analyzer with the updated FFT size
|
||||
analyzer = getAnalyser(app.osc.fftSize);
|
||||
dataArray = new Float32Array(analyzer.frequencyBinCount);
|
||||
}
|
||||
@ -252,7 +261,7 @@ export const runOscilloscope = (
|
||||
-OFFSET_WIDTH,
|
||||
-OFFSET_HEIGHT,
|
||||
WIDTH + 2 * OFFSET_WIDTH,
|
||||
HEIGHT + 2 * OFFSET_HEIGHT,
|
||||
HEIGHT + 2 * OFFSET_HEIGHT
|
||||
);
|
||||
}
|
||||
canvasCtx.lineWidth = app.osc.thickness;
|
||||
|
||||
11
src/Clock.ts
11
src/Clock.ts
@ -48,10 +48,7 @@ export class Clock {
|
||||
lastPlayPressTime: number;
|
||||
totalPauseTime: number;
|
||||
|
||||
constructor(
|
||||
public app: Editor,
|
||||
ctx: AudioContext,
|
||||
) {
|
||||
constructor(public app: Editor, ctx: AudioContext) {
|
||||
this.time_position = { bar: 0, beat: 0, pulse: 0 };
|
||||
this.time_signature = [4, 4];
|
||||
this.logicalTime = 0;
|
||||
@ -77,6 +74,12 @@ export class Clock {
|
||||
}
|
||||
|
||||
convertTicksToTimeposition(ticks: number): TimePosition {
|
||||
/**
|
||||
* Converts ticks to a TimePosition object.
|
||||
* @param ticks The number of ticks to convert.
|
||||
* @returns The TimePosition object representing the converted ticks.
|
||||
*/
|
||||
|
||||
const beatsPerBar = this.app.clock.time_signature[0];
|
||||
const ppqnPosition = ticks % this.app.clock.ppqn;
|
||||
const beatNumber = Math.floor(ticks / this.app.clock.ppqn);
|
||||
|
||||
@ -47,7 +47,7 @@ export const makeExampleFactory = (application: Editor): Function => {
|
||||
const make_example = (
|
||||
description: string,
|
||||
code: string,
|
||||
open: boolean = false,
|
||||
open: boolean = false
|
||||
) => {
|
||||
const codeId = `codeExample${application.exampleCounter++}`;
|
||||
// Store the code snippet in the data structure
|
||||
@ -70,7 +70,11 @@ export const makeExampleFactory = (application: Editor): Function => {
|
||||
};
|
||||
|
||||
export const documentation_factory = (application: Editor) => {
|
||||
// Initialize a data structure to store code examples by their unique IDs
|
||||
/**
|
||||
* Creates the documentation for the given application.
|
||||
* @param application The editor application.
|
||||
* @returns An object containing various documentation sections.
|
||||
*/
|
||||
application.api.codeExamples = {};
|
||||
|
||||
return {
|
||||
@ -109,6 +113,10 @@ export const documentation_factory = (application: Editor) => {
|
||||
};
|
||||
|
||||
export const showDocumentation = (app: Editor) => {
|
||||
/**
|
||||
* Shows or hides the documentation based on the current state of the app.
|
||||
* @param app - The Editor instance.
|
||||
*/
|
||||
if (document.getElementById("app")?.classList.contains("hidden")) {
|
||||
document.getElementById("app")?.classList.remove("hidden");
|
||||
document.getElementById("documentation")?.classList.add("hidden");
|
||||
@ -129,6 +137,9 @@ export const showDocumentation = (app: Editor) => {
|
||||
};
|
||||
|
||||
export const hideDocumentation = () => {
|
||||
/**
|
||||
* Hides the documentation section and shows the main application.
|
||||
*/
|
||||
if (document.getElementById("app")?.classList.contains("hidden")) {
|
||||
document.getElementById("app")?.classList.remove("hidden");
|
||||
document.getElementById("documentation")?.classList.add("hidden");
|
||||
@ -136,6 +147,12 @@ export const hideDocumentation = () => {
|
||||
};
|
||||
|
||||
export const updateDocumentationContent = (app: Editor, bindings: any) => {
|
||||
/**
|
||||
* Updates the content of the documentation pane with the converted markdown.
|
||||
*
|
||||
* @param app - The editor application.
|
||||
* @param bindings - Additional bindings for the showdown converter.
|
||||
*/
|
||||
const converter = new showdown.Converter({
|
||||
emoji: true,
|
||||
moreStyling: true,
|
||||
@ -143,7 +160,7 @@ export const updateDocumentationContent = (app: Editor, bindings: any) => {
|
||||
extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
|
||||
});
|
||||
const converted_markdown = converter.makeHtml(
|
||||
app.docs[app.currentDocumentationPane],
|
||||
app.docs[app.currentDocumentationPane]
|
||||
);
|
||||
document.getElementById("documentation-content")!.innerHTML =
|
||||
converted_markdown;
|
||||
|
||||
@ -63,6 +63,12 @@ export const buttonGroups = {
|
||||
|
||||
//@ts-ignore
|
||||
export const createDocumentationStyle = (app: Editor) => {
|
||||
/**
|
||||
* Creates a documentation style object.
|
||||
* @param {Editor} app - The editor object.
|
||||
* @returns {Object} - The documentation style object.
|
||||
*/
|
||||
|
||||
return {
|
||||
h1: "text-white lg:text-4xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 border-b-4 pt-4 pb-3 px-2",
|
||||
h2: "text-white lg:text-3xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 border-b-2 pt-12 pb-3 px-2",
|
||||
|
||||
@ -8,11 +8,19 @@ const codeReplace = (code: string): string => {
|
||||
|
||||
const tryCatchWrapper = async (
|
||||
application: Editor,
|
||||
code: string,
|
||||
code: string
|
||||
): Promise<boolean> => {
|
||||
/**
|
||||
* Wraps the provided code in a try-catch block and executes it.
|
||||
*
|
||||
* @param application - The editor application.
|
||||
* @param code - The code to be executed.
|
||||
* @returns A promise that resolves to a boolean indicating whether the code executed successfully or not.
|
||||
*/
|
||||
|
||||
try {
|
||||
await new Function(`"use strict"; ${codeReplace(code)}`).call(
|
||||
application.api,
|
||||
application.api
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
@ -26,18 +34,32 @@ const cache = new Map<string, Function>();
|
||||
const MAX_CACHE_SIZE = 40;
|
||||
|
||||
const addFunctionToCache = (code: string, fn: Function) => {
|
||||
/**
|
||||
* Adds a function to the cache.
|
||||
* @param code - The code associated with the function.
|
||||
* @param fn - The function to be added to the cache.
|
||||
*/
|
||||
if (cache.size >= MAX_CACHE_SIZE) {
|
||||
cache.delete(cache.keys().next().value);
|
||||
}
|
||||
cache.set(code, fn);
|
||||
};
|
||||
|
||||
// Optimized evaluate function with reduced complexity
|
||||
export const tryEvaluate = async (
|
||||
application: Editor,
|
||||
code: File,
|
||||
timeout = 5000,
|
||||
timeout = 5000
|
||||
): Promise<void> => {
|
||||
/**
|
||||
* Tries to evaluate the provided code within a specified timeout period.
|
||||
* Increments the evaluation count of the code file.
|
||||
* If the code is valid, updates the committed code and adds the evaluated function to the cache.
|
||||
* If the code is invalid, retries the evaluation.
|
||||
* @param application - The editor application.
|
||||
* @param code - The code file to evaluate.
|
||||
* @param timeout - The timeout period in milliseconds (default: 5000).
|
||||
* @returns A Promise that resolves when the evaluation is complete.
|
||||
*/
|
||||
code.evaluations!++;
|
||||
const candidateCode = code.candidate;
|
||||
|
||||
@ -55,7 +77,7 @@ export const tryEvaluate = async (
|
||||
if (isCodeValid) {
|
||||
code.committed = code.candidate;
|
||||
const newFunction = new Function(
|
||||
`"use strict"; ${codeReplace(wrappedCode)}`,
|
||||
`"use strict"; ${codeReplace(wrappedCode)}`
|
||||
);
|
||||
addFunctionToCache(candidateCode, newFunction);
|
||||
} else {
|
||||
@ -71,8 +93,16 @@ export const tryEvaluate = async (
|
||||
export const evaluate = async (
|
||||
application: Editor,
|
||||
code: File,
|
||||
timeout = 1000,
|
||||
timeout = 1000
|
||||
): Promise<void> => {
|
||||
/**
|
||||
* Evaluates the given code using the provided application and timeout.
|
||||
* @param application The editor application.
|
||||
* @param code The code file to evaluate.
|
||||
* @param timeout The timeout value in milliseconds (default: 1000).
|
||||
* @returns A Promise that resolves when the evaluation is complete.
|
||||
*/
|
||||
|
||||
try {
|
||||
await Promise.race([
|
||||
tryCatchWrapper(application, code.committed as string),
|
||||
@ -87,7 +117,7 @@ export const evaluate = async (
|
||||
|
||||
export const evaluateOnce = async (
|
||||
application: Editor,
|
||||
code: string,
|
||||
code: string
|
||||
): Promise<void> => {
|
||||
/**
|
||||
* Evaluates the code once without any caching or error-handling mechanisms besides the tryCatchWrapper.
|
||||
|
||||
@ -154,7 +154,7 @@ export class AppSettings {
|
||||
|
||||
constructor() {
|
||||
const settingsFromStorage = JSON.parse(
|
||||
localStorage.getItem("topos") || "{}",
|
||||
localStorage.getItem("topos") || "{}"
|
||||
);
|
||||
|
||||
if (settingsFromStorage && Object.keys(settingsFromStorage).length !== 0) {
|
||||
@ -210,7 +210,7 @@ export class AppSettings {
|
||||
|
||||
saveApplicationToLocalStorage(
|
||||
universes: Universes,
|
||||
settings: Settings,
|
||||
settings: Settings
|
||||
): void {
|
||||
/**
|
||||
* Main method to store the application to local storage.
|
||||
@ -273,6 +273,11 @@ export const emptyUrl = () => {
|
||||
};
|
||||
|
||||
export const share = async (app: Editor) => {
|
||||
/**
|
||||
* Shares the current state of the app by generating a URL with encoded data and copying it to the clipboard.
|
||||
* @param app - The Editor instance representing the app.
|
||||
* @returns A Promise that resolves to void.
|
||||
*/
|
||||
async function bufferToBase64(buffer: Uint8Array) {
|
||||
const base64url: string = await new Promise((r) => {
|
||||
const reader = new FileReader();
|
||||
@ -323,8 +328,20 @@ export const loadUniverserFromUrl = (app: Editor): void => {
|
||||
export const loadUniverse = (
|
||||
app: Editor,
|
||||
universeName: string,
|
||||
universe: Universe = template_universe,
|
||||
universe: Universe = template_universe
|
||||
): void => {
|
||||
/**
|
||||
* Loads a universe into the application.
|
||||
* If the universe does not exist, a fresh clone of the template universe is created and added to the application.
|
||||
* The references to the selected universe are updated in the application settings.
|
||||
* The editor view is updated to reflect the selected universe.
|
||||
* The initialization script for the selected universe is evaluated.
|
||||
*
|
||||
* @param app - The Editor application instance.
|
||||
* @param universeName - The name of the universe to load.
|
||||
* @param universe - The template universe to clone if the specified universe does not exist.
|
||||
*/
|
||||
|
||||
let selectedUniverse = universeName.trim();
|
||||
if (app.universes[selectedUniverse] === undefined) {
|
||||
// Pushing a freshly cloned template universe to:
|
||||
@ -346,7 +363,11 @@ export const loadUniverse = (
|
||||
};
|
||||
|
||||
export const openUniverseModal = (): void => {
|
||||
// If the modal is hidden, unhide it and hide the editor
|
||||
/**
|
||||
* Opens the universe modal.
|
||||
* If the modal is hidden, it unhides it and hides the editor.
|
||||
* If the modal is already visible, it closes the modal.
|
||||
*/
|
||||
if (
|
||||
document.getElementById("modal-buffers")!.classList.contains("invisible")
|
||||
) {
|
||||
@ -359,6 +380,9 @@ export const openUniverseModal = (): void => {
|
||||
};
|
||||
|
||||
export const closeUniverseModal = (): void => {
|
||||
/**
|
||||
* Closes the universe modal and performs necessary actions.
|
||||
*/
|
||||
// @ts-ignore
|
||||
document.getElementById("buffer-search")!.value = "";
|
||||
document.getElementById("editor")!.classList.remove("invisible");
|
||||
@ -366,6 +390,9 @@ export const closeUniverseModal = (): void => {
|
||||
};
|
||||
|
||||
export const openSettingsModal = (): void => {
|
||||
/**
|
||||
* Opens the settings modal.
|
||||
*/
|
||||
if (
|
||||
document.getElementById("modal-settings")!.classList.contains("invisible")
|
||||
) {
|
||||
@ -377,6 +404,9 @@ export const openSettingsModal = (): void => {
|
||||
};
|
||||
|
||||
export const closeSettingsModal = (): void => {
|
||||
/**
|
||||
* Closes the settings modal and performs necessary actions.
|
||||
*/
|
||||
document.getElementById("editor")!.classList.remove("invisible");
|
||||
document.getElementById("modal-settings")!.classList.add("invisible");
|
||||
};
|
||||
|
||||
67
src/main.ts
67
src/main.ts
@ -101,6 +101,19 @@ export class Editor {
|
||||
public hydra: any;
|
||||
|
||||
constructor() {
|
||||
/**
|
||||
* This is the entry point of the application. The Editor instance is created when the page is loaded.
|
||||
* It is responsible for:
|
||||
* - Initializing the user interface
|
||||
* - Loading the universe from local storage
|
||||
* - Initializing the audio context and the clock
|
||||
* - Building the user API
|
||||
* - Building the documentation
|
||||
* - Installing event listeners
|
||||
* - Building the CodeMirror editor
|
||||
* - Evaluating the init file
|
||||
*/
|
||||
|
||||
// ================================================================================
|
||||
// Build user interface
|
||||
// ================================================================================
|
||||
@ -194,6 +207,11 @@ export class Editor {
|
||||
}
|
||||
|
||||
private getBuffer(type: string): any {
|
||||
/**
|
||||
* Retrieves the buffer based on the specified type.
|
||||
* @param type - The type of buffer to retrieve.
|
||||
* @returns The buffer object.
|
||||
*/
|
||||
const universe = this.universes[this.selected_universe.toString()];
|
||||
return type === "locals"
|
||||
? universe[type][this.local_index]
|
||||
@ -221,6 +239,12 @@ export class Editor {
|
||||
}
|
||||
|
||||
updateKnownUniversesView = () => {
|
||||
/**
|
||||
* Updates the known universes view.
|
||||
* This function generates and populates a list of known universes based on the data stored in the 'universes' property.
|
||||
* It retrieves the necessary HTML elements and template, creates the list, and attaches event listeners to the generated items.
|
||||
* If any required elements or templates are missing, warning messages are logged and the function returns early.
|
||||
*/
|
||||
let itemTemplate = document.getElementById(
|
||||
"ui-known-universe-item-template"
|
||||
) as HTMLTemplateElement;
|
||||
@ -261,7 +285,13 @@ export class Editor {
|
||||
};
|
||||
|
||||
changeToLocalBuffer(i: number) {
|
||||
// Updating the CSS accordingly
|
||||
/**
|
||||
* Changes the local buffer based on the provided index.
|
||||
* Updates the CSS accordingly by adding a specific class to the selected tab and removing it from other tabs.
|
||||
* Updates the local index and updates the editor view.
|
||||
*
|
||||
* @param i The index of the tab to change the local buffer to.
|
||||
*/
|
||||
const tabs = document.querySelectorAll('[id^="tab-"]');
|
||||
const tab = tabs[i] as HTMLElement;
|
||||
tab.classList.add("bg-orange-300");
|
||||
@ -274,6 +304,11 @@ export class Editor {
|
||||
}
|
||||
|
||||
changeModeFromInterface(mode: "global" | "local" | "init" | "notes") {
|
||||
/**
|
||||
* Changes the mode of the interface.
|
||||
*
|
||||
* @param mode - The mode to change to. Can be one of "global", "local", "init", or "notes".
|
||||
*/
|
||||
const interface_buttons: HTMLElement[] = [
|
||||
this.interface.local_button,
|
||||
this.interface.global_button,
|
||||
@ -345,6 +380,12 @@ export class Editor {
|
||||
button: "play" | "pause" | "stop" | "clear",
|
||||
highlight: boolean
|
||||
) {
|
||||
/**
|
||||
* Sets the highlighting for a specific button.
|
||||
*
|
||||
* @param button - The button to highlight ("play", "pause", "stop", or "clear").
|
||||
* @param highlight - A boolean indicating whether to highlight the button or not.
|
||||
*/
|
||||
document.getElementById("play-label")!.textContent =
|
||||
button !== "pause" ? "Pause" : "Play";
|
||||
if (button !== "pause") {
|
||||
@ -429,12 +470,12 @@ export class Editor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flashes the background of the view and its gutters.
|
||||
* @param {string} color - The color to set.
|
||||
* @param {number} duration - Duration in milliseconds to maintain the color.
|
||||
*/
|
||||
flashBackground(color: string, duration: number): void {
|
||||
/**
|
||||
* Flashes the background of the view and its gutters.
|
||||
* @param {string} color - The color to set.
|
||||
* @param {number} duration - Duration in milliseconds to maintain the color.
|
||||
*/
|
||||
const domElement = this.view.dom;
|
||||
const gutters = domElement.getElementsByClassName(
|
||||
"cm-gutter"
|
||||
@ -480,6 +521,12 @@ export class Editor {
|
||||
}
|
||||
|
||||
private loadHydraSynthAsync(): void {
|
||||
/**
|
||||
* Loads the Hydra Synth asynchronously by creating a script element
|
||||
* and appending it to the document head. * Once the script is
|
||||
* loaded successfully, it initializes the Hydra Synth. If there
|
||||
* is an error loading the script, it logs an error message.
|
||||
*/
|
||||
var script = document.createElement("script");
|
||||
script.src = "https://unpkg.com/hydra-synth";
|
||||
script.async = true;
|
||||
@ -494,6 +541,9 @@ export class Editor {
|
||||
}
|
||||
|
||||
private initializeHydra(): void {
|
||||
/**
|
||||
* Initializes the Hydra backend and sets up the Hydra synth.
|
||||
*/
|
||||
// @ts-ignore
|
||||
this.hydra_backend = new Hydra({
|
||||
canvas: this.interface.hydra_canvas as HTMLCanvasElement,
|
||||
@ -506,6 +556,11 @@ export class Editor {
|
||||
}
|
||||
|
||||
private setCanvas(canvas: HTMLCanvasElement): void {
|
||||
/**
|
||||
* Sets the canvas element and configures its size and context.
|
||||
*
|
||||
* @param canvas - The HTMLCanvasElement to set.
|
||||
*/
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext("2d");
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
|
||||
Reference in New Issue
Block a user