Components #
These web components are custom elements (DOM elements) that serve as building blocks to make web software.
Requirements #
- Components should never rely on instances of other components, except if they live in the 'orchestrator' category or if the instance is a child of itself. Orchestrator components can refer to other components using a DOM selector, this can be provided via an attribute ending with
-selectoras its name. These orchestrators are responsible for bringing components together and making prebuilt setups. - Components rely on signals exposed via the
common/signal.jsmodule. Only signal getters are exposed, never the entire signal object. - A base class should be built that all components build on. This should be made available via
common/element.js. - Components should be broadcastable, meaning that various instances of that component should be able to communicate with each other. This will be used to replicate state and call methods. Broadcasting should have two modes: 'replicate' and 'leaderOnly'. The former is executed on all instances, while the latter is only executed on the leader. Another base class should be provided for broadcastable components. A
groupattribute will be used to choose the group in which we'll broadcast, so can we can form groups of instances that communicate. - Components live in the
componentsdirectory. - Another special category of components is 'configurator', those components take DOM children of the same category. For example, A configurator must have at least the same properties as the component provided via the DOM, but may have more.
- If heavy computation work or other work which could block the main thread is needed, the element should be accompanied by a web worker.
- A tunnel should be able to be formed between workers using message ports, passing the message port along using
postMessage. - Communication between different threads/workers should be performant.
- Register the custom element as soon as possible. Ideally using the
defineElementhelper to prevent double registration. - When any namespace is needed, prefer to prefix with
diffuse/ - When code is shared between files from a specific component, components in a specific category, or components across different categories; put it in a
common.jsfile (orcommondirectory with multiple js files if it gets too big) on the appropriate level. - Tag naming convention: all lowercase, starts with letter
d, then the first letter of each sub category, a dash, and finally the name of the element in kebab case. Collisions may occur with the prefix, in that case, change the element name. - All elements should have a
static NAMEproperty with the directory path in src prefixed withdiffuse/.
Other categories #
Artwork #
Various ways to fetch artwork for tracks. Must adhere to types defined in artwork/types.d.ts
Engine #
All kinds of core behaviour.
Input #
Input components generate tracks and resolve track URIs into audio. They must adhere to types defined in input/types.d.ts
Metadata #
Various ways to fetch metadata for tracks. Must adhere to types defined in metadata/types.d.ts
Upload #
Upload components handle uploading audio files to cloud storage (e.g. Dropbox) and deleting them again. They are paired with input components by scheme: an upload component's SCHEME matches the input component that can resolve the URIs it produces. upload() returns a URI carrying that scheme, which is stored on a track; the matching input component can then resolve it, and delete() the file remotely. Must adhere to types defined in upload/types.d.ts
Output #
Output components hold all the user data: facets, playlist items, settings and tracks. They all have the same surface API. Data is exposed via a signal getter called collection, one for each kind of data. These components are also responsible loading and saving that data. The data may be encoded, each component decides for its own what the type of the data is. The subcategory states what that type is and this is reflected in the directory structure these components live in:
polymorphic: The data can be of multiple types.raw: The data is not encoded at all, it is of the same type stated in the definitions (lexicons).bytes: Encoded asUint8Array.
Must adhere to types defined in output/types.d.ts
Supplement #
All kinds of additional components, not really required to make a working audio player application. Scrobbling for example.
Transformer #
Transformers are also intermediate components like configurators, with the same API requirements. They don't take DOM elements as children however, instead they serve to be used as a chain. Output transformers have a output-selector which chains the transformer to another component. These output transformers also have the same subcategories and directory structure as the output category.