Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Action Properties #51

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"babel-loader": "^8.2.3",
"babel-plugin-module-resolver": "^4.1.0",
"babel-plugin-module-resolver": "^5.0.0",
"eslint": "^8.8.0",
"jest": "^27.4.7",
"jest-filename-transform": "^0.1.0",
Expand Down
94 changes: 94 additions & 0 deletions src/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ActionEvents } from "./events";
import { State, StateProps } from "./State";
import { Target } from "./Target";
import type { Plugin } from "./Plugin";
import { Encoder } from "./Encoder";

/**
* The Action must match a few files:
Expand Down Expand Up @@ -90,6 +91,44 @@ export class Action<
*/
public device = "";

/**
* Defines how the action interacts with Dial buttons on the SD+
* By default this is not set and actions don't list Encoder as a Controller.
* @type {Encoder}
*/
public encoder: Encoder = undefined as unknown as Encoder;

/**
* Defines if the Action is allowed on a KeyPad button.
* `true` by default for backwards compatibility.
*
* @type {boolean}
*/
public keyPad = true;

/**
* Boolean to disable the title field for users in the property inspector.
* True by default.
*
* @type {boolean}
*/
public enableUserTitle = true;

/**
* Boolean to hide the action in the actions list. This can be used for a
* plugin that only works with a specific profile. True by default.
*
* @type {boolean}
*/
public isVisibleInActionsList = true;

/**
* Boolean to disable image caching. False by default.
*
* @type {boolean}
*/
public disableCachingImages = false;

constructor(params: {
name: string;
inspectorName?: string;
Expand Down Expand Up @@ -117,6 +156,18 @@ export class Action<
States: this.states.map((s) => s.toManifest()),
};

const controllers: string[] = [];

if (this.encoder !== undefined) {
controllers.push("Encoder");
}

if (this.keyPad === true) {
controllers.push("KeyPad");
}

snippet.Controllers = controllers as unknown as string[];

const optionals: [string, unknown, unknown][] = [
[
"PropertyInspectorPath",
Expand All @@ -129,6 +180,19 @@ export class Action<
this.hasMultiActionSupport === false,
this.hasMultiActionSupport,
],
// ["Controllers", controllers],
["Encoder", this.encoder !== undefined, this.encoder.toManifest()],
[
"UserTitleEnabled",
this.enableUserTitle === false,
this.enableUserTitle,
],
[
"VisibleInActionsList",
this.isVisibleInActionsList === false,
this.isVisibleInActionsList,
],
["DisableCaching", this.disableCachingImages, this.disableCachingImages],
];

optionals.forEach(([prop, condition, value]) => {
Expand Down Expand Up @@ -406,4 +470,34 @@ export class Action<
payload: { profile },
});
}

/**
* Send event to dynamically change properties of the SD+ touch display
* @param {Record<string, unknown>} payload Key/Value pairs of properties to
* change
* @return {void}
*/
public setFeedback(payload: Record<string, unknown>) {
this.send({
event: "setFeedback",
context: this.context,
payload,
});
}

/**
* Send an event to dynamically change the layout of a SD+ touch display
* @param {string} layout Internal `id` of built-in layout or path to json
* file that contains a custom layout
* @return {void}
*/
public setFeedbackLayout(layout: string) {
this.send({
event: "setFeedbackLayout",
context: this.context,
payload: {
layout,
},
});
}
}
122 changes: 122 additions & 0 deletions src/Encoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/**
* The encoder is used to configure the dial and display segment on an SD+.
* It is completely optional.
*/
export class Encoder {
/**
* Default background for the touch display slot
* @type {string}
*/
public background?: string;

/**
* Default icon for the Property Inspector, dial stack and layout. Falls back
* to the Action List Icon
*
* @type {string}
*/
public icon?: string;

/**
* Either a built-in layout (string) or a path to a JSON file that describes
* a custom layout. Can be changed with `setFeedbackLayout` event.
* @see Layout
* @type {string}
*/
public layout?: string;

/**
* The color used as the background of the Dial Stack
* @type {string}
*/
public stackColor?: string;

/**
* Part of TriggerDescription. Describes the action performed on rotation of
* the dial
* @type {string}
*/
public onRotateDescription?: string;

/**
* Part of TriggerDescription. Describes the action performed on pressing of
* the dial
* @type {string}
*/
public onPushDescription?: string;

/**
* Part of TriggerDescription. Describes the action performed on touching the
* display pad
* @type {string}
*/
public onTouchDescription?: string;

/**
* Part of TriggerDescription. Describes the action performed on long pressing
* the display pad
* @type {string}
*/
public onLongTouchDescription?: string;

public toManifest(): Record<string, unknown> {
const snippet: Record<string, unknown> = {
background: this.background,
Icon: this.icon,
layout: this.layout,
StackColor: this.stackColor,
TriggerDescription: {
Rotate: this.onRotateDescription,
Push: this.onPushDescription,
Touch: this.onTouchDescription,
LongTouch: this.onLongTouchDescription,
},
};

const optionals: [string, unknown, unknown][] = [
["background", this.background, this.background],
["Icon", this.icon, this.icon],
["layout", this.layout, this.layout],
["StackColor", this.stackColor, this.stackColor],
["StackColor", this.stackColor, this.stackColor],
[
"TriggerDescription",
this.onRotateDescription ||
this.onPushDescription ||
this.onTouchDescription ||
this.onLongTouchDescription,
this.buildTriggerDescription(),
],
];

this.evaluateOptionalValues(optionals, snippet);
return snippet;
}

private buildTriggerDescription() {
const snippet: Record<string, unknown> = {};

const optionals: [string, unknown, unknown][] = [
["Rotate", this.onRotateDescription, this.onRotateDescription],
["Push", this.onPushDescription, this.onPushDescription],
["Touch", this.onTouchDescription, this.onTouchDescription],
["LongTouch", this.onLongTouchDescription, this.onLongTouchDescription],
];

this.evaluateOptionalValues(optionals, snippet);
return snippet;
}

private evaluateOptionalValues(
optionals: [string, unknown, unknown][],
object: Record<string, unknown>,
): Record<string, unknown> {
optionals.forEach(([prop, condition, value]) => {
if (condition) {
object[prop] = value;
}
});

return object;
}
}
Loading
Loading