Northern Pileated Marmoset

    streamdeck-typescript
    TypeScript icon, indicating that this package has built-in type declarations

    3.1.4 • Public • Published

    Forks Stars Watchers Contributors

    Issues Issues closed

    Issues-pr Issues-pr closed PRs welcome

    Sonar Quality Gate npm

    GitHub license Awesome Badges

    Stream Deck TS-SDK

    A library that helps you develop plugins for Elgato's Stream Deck.

    Installation

    • Install via npm:
    npm install --save streamdeck-typescript

    Decorators

    This Plugin adds a few decorators for classes and methods.

    Available decorators

    • methods
      • @SDOnPiEvent(event) - Listens for specified event in the property inspector context and if triggered, calls method
        • Overhands EventData (*NameOfEvent*Event; Example: KeyDownEvent, KeyUpEvent, WillAppearEvent)
      • @SDOnActionEvent(event) - Listens for specified event in the action context and if triggered, calls method
        • Overhands EventData (*NameOfEvent*Event; Example: KeyDownEvent, KeyUpEvent, WillAppearEvent)

    Usage

    You can see an example in the example folder or look through the Source docs

    Initializing Plugin

    Elgato uses 2 different files. The Action file (which handels all actions), and the Property Inspector file (which is for settings)

    counter.ts

    import {StreamDeckPluginHandler} from '../src';
    import {CounterAction}           from './actions/counter.action';
    
    export class Counter extends StreamDeckPluginHandler {
        constructor() {
            super();
            new CounterAction(this, 'fun.shiro.counter.action');
        }
    }
    
    new Counter();

    plugin.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<title>Test Plugin</title>
    	<meta charset="utf-8">
    	<script src="dist/bundle.js"></script>
    </head>
    <body>
    </body>
    </html>

    Here you can see. After the build you have only one file (bundle.js in this case) and this gets loaded.

    counter-pi.ts

    import {DidReceiveSettingsEvent, SDOnPiEvent, StreamDeckPropertyInspectorHandler} from '../src';
    import {SettingsInterface}                                                        from './interfaces/settings.interface';
    
    class CounterPi extends StreamDeckPropertyInspectorHandler {
        private count: HTMLInputElement;
        private stepsCount: HTMLInputElement;
    
        constructor() {
            super();
        }
    
        @SDOnPiEvent('documentLoaded')
        onDocumentReady() {
            this.count = document.getElementById('count') as HTMLInputElement;
            this.count.addEventListener('keyup', () =>
                this.settingsManager.setContextSettingsAttributes(
                    this.actionInfo.context, {count: this.count.valueAsNumber}, 500));
            this.stepsCount = document.getElementById('steps') as HTMLInputElement;
            this.stepsCount.addEventListener('keyup', () =>
                this.settingsManager.setContextSettingsAttributes(
                    this.actionInfo.context, {steps: this.stepsCount.valueAsNumber}, 500));
    
            const settings = this.settingsManager.getContextSettings<SettingsInterface>(this.actionInfo.context);
    
            this.count.value = (settings?.count ?? 0).toString();
            this.stepsCount.value = (settings?.steps ?? 1).toString();
        }
    
        @SDOnPiEvent('didReceiveSettings')
        private onSettingsReceived({payload: {settings}}: DidReceiveSettingsEvent<SettingsInterface>) {
            if (Object.keys(settings).length <= 0)
                return;
    
            this.count.value = settings.count.toString() ?? 0;
            this.stepsCount.value = settings.steps.toString() ?? 1;
        }
    }
    
    new CounterPi();

    property-inspector.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<title>Test Plugin Inspector</title>
    	<meta charset="utf-8">
    	<link rel="stylesheet" href="sdpi.css">
    	<script src="dist/bundle-pi.js"></script>
    </head>
    <body>
    <div class="sdpi-wrapper" id="mainSettings">
    	<div class="sdpi-item">
    		<div class="sdpi-item-label">Count</div>
    		<input class="sdpi-item-value" type="number" id="count" value="0">
    	</div>
    	<div class="sdpi-item">
    		<div class="sdpi-item-label">Steps</div>
    		<input class="sdpi-item-value" type="number" id="steps" value="1">
    	</div>
    </div>
    </body>
    </html>

    counter.action.ts

    import {
        DidReceiveSettingsEvent,
        KeyDownEvent,
        KeyUpEvent,
        SDOnActionEvent,
        StreamDeckAction,
        WillAppearEvent
    }                          from '../../src';
    import {Counter}           from '../counter';
    import {SettingsInterface} from '../interfaces/settings.interface';
    
    export class CounterAction extends StreamDeckAction<Counter, CounterAction> {
        private keyUpTimer: any;
    
        constructor(private plugin: Counter, private actionName: string) {
            super(plugin, actionName);
        }
    
        @SDOnActionEvent('willAppear')
        private onAppear({context, payload: {settings}}: WillAppearEvent<SettingsInterface>) {
            this.plugin.setTitle((settings.count ?? 0).toString(), context);
        }
    
        @SDOnActionEvent('keyUp')
        private onKeyUp({context, payload: {settings}}: KeyUpEvent<SettingsInterface>) {
            clearTimeout(this.keyUpTimer);
            const steps = settings.steps ?? 1;
            const count = (settings.count ?? 0) + steps;
            this.plugin.setTitle(count.toString(), context);
            this.plugin.setSettings<SettingsInterface>({steps, count}, context);
        }
    
        @SDOnActionEvent('keyDown')
        private onKeyDown({context, payload: {settings}}: KeyDownEvent<SettingsInterface>) {
            this.keyUpTimer = setTimeout(() => {
                const steps = settings.steps ?? 1;
                this.plugin.setSettings<SettingsInterface>(
                    {
                        steps,
                        count: steps * -1
                    }, context
                );
                this.plugin.setTitle('0', context);
            }, 2000);
        }
    
        @SDOnActionEvent('didReceiveSettings')
        private onSettings({context, payload: {settings}}: DidReceiveSettingsEvent<SettingsInterface>) {
            this.plugin.setTitle(settings.count.toString() ?? 0, context);
        }
    }

    settings.interface.ts

    export interface SettingsInterface {
        count: number,
        steps: number
    }

    Building the Plugin

    I would suggest you to do it like in the example with browserify, terser, tsify, typescript and for development watchify

    See package.json and tsconfig.json

    {
        "scripts": {
            "build": "tsc -p tsconfig.json",
            "build-example": "browserify -p tsify example/counter-pi.ts | terser -cm --comments false -o dist/bundle-pi.js && browserify -p tsify example/counter.ts | terser -cm --comments false -o dist/bundle.js",
            "watch": "start watchify --debug -p tsify example/counter.ts -o dist/bundle.js && start watchify --debug -p tsify example/counter-pi.ts -o dist/bundle-pi.js",
            "documentation": "typedoc src/index.ts",
            "test": "echo \"Error: no test specified\" && exit 1"
        }
    }

    How to contribute?

    Just fork the repository and create PR's, but we use standard-version to optimal release the plugin.

    standard-version is following the conventionalcommits specification which follows the angular commit guidelines

    Install

    npm i streamdeck-typescript

    DownloadsWeekly Downloads

    7

    Version

    3.1.4

    License

    MIT

    Unpacked Size

    1.3 MB

    Total Files

    236

    Last publish

    Collaborators

    • xeroxdev