0

I use Intellij IDEA and Vaadin 14. How can i convert simple Polymer component to Lit with TypeScript? I want to learn how to create Lit with TypeScript in order to upgrade project to latest Vaadin LTS, that is use it as i understand. I tried to create ts-file based on included JS-file, but have no luck. It highlite many errors for the code. Maybe someone can give some links where i can read more pointly about this?

AudioPlayer.java:

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.polymertemplate.EventHandler;
import com.vaadin.flow.component.polymertemplate.PolymerTemplate;
import com.vaadin.flow.server.StreamReceiver;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.StreamResourceRegistry;
import com.vaadin.flow.server.StreamVariable;
import org.apache.commons.io.input.AutoCloseInputStream;

import java.io.InputStream;
import java.util.function.Supplier;

@Tag("audio-player-element")
@JsModule("./src/audio-player/audio-player-element.js")
public class AudioPlayer extends PolymerTemplate<AudioPlayerModel> {


    private Supplier<InputStream> inputStreamSupplier;

    public AudioPlayer(Supplier<InputStream> inputStreamSupplier) {
        this.inputStreamSupplier = inputStreamSupplier;
    }

    @EventHandler
    private void requestAudioStream() {
        if (getModel().getAudioSrc() == null) {
            AutoCloseInputStream autoCloseInputStream = new AutoCloseInputStream(inputStreamSupplier.get());
            StreamResource streamResource = new StreamResource(
                    "audio_proxy_" + System.currentTimeMillis() + ".webm",
                    () -> autoCloseInputStream);
            streamResource.setCacheTime(600000);
            streamResource.setContentType("application/octet-stream");
            getElement().setAttribute("streamResourceHandler", streamResource);
            String src = StreamResourceRegistry.getURI(streamResource).getPath();
            getModel().setAudioSrc(src);
        }
        getElement().executeJs("this.audioPlay();");
    }
}

AudioPlayerModel.java:

import com.vaadin.flow.templatemodel.TemplateModel;

public class AudioPlayerModel implements TemplateModel {

    private String audioSrc;

    public String getAudioSrc() {
        return audioSrc;
    }

    public void setAudioSrc(String audioSrc) {
        this.audioSrc = audioSrc;
    }
}

audio-player-element.js:

import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-icons/vaadin-icons.js';
import '@polymer/iron-icon/iron-icon.js';

class AudioPlayerElement extends PolymerElement {


    constructor() {
        super();
    }


    static get template() {
        return html`
            <div class="audio-container" on-click="requestAudioStream">
                <iron-icon class="play-pause-icon"
                           icon="[[playButtonIcon]]"
                ></iron-icon>
                <audio id="audioPlayer" src$=[[audioSrc]] on-ended="onAudioEnded"/>
            </div>
            ${this.templateCSS}
        `;
    }


    static get is() {
        return 'audio-player-element';
    }

    static get properties() {
        return {
            playButtonIcon: {
                type: String,
                value: "vaadin:play",
                notify: true
            },
            audioSrc: {
                type: String,
                value: null,
                notify: true/*,
                reflectToAttribute: true*/
            }
        }
    }

    /* Backend alias */
    requestAudioStream() {}


    audioPlay() {
        this.playButtonIcon = "vaadin:stop";
        this.$.audioPlayer.play();
    }

    onAudioEnded() {
        this.$.audioPlayer.currentTime = 0;
        this.playButtonIcon = "vaadin:play";
    }

    static get templateCSS() {
        return html`
            <style>
                :host div.audio-container {
                    width: 50px;
                    border-radius: 7px;
                    padding: 3px;
                    display: inline-flex;
                    flex-direction: row;
                    flex-wrap: nowrap;
                    justify-content: flex-start;
                    box-shadow: inset 0 0 2px 1px #0087fd;
                    margin: 3px;
                    height: 15px;
                }
                :host div iron-icon.play-pause-icon {
                    width: 18px;
                    height: 18px;
                    display: contents;
                }
            </style>`;
    }
}
customElements.define(AudioPlayerElement.is, AudioPlayerElement);
lanmaster
  • 330
  • 2
  • 16

1 Answers1

0

Resolved.

Java:

// AudioPlayer2.java
import com.vaadin.flow.component.ClientCallable;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.StreamResourceRegistry;
import org.apache.commons.io.input.AutoCloseInputStream;

import java.io.InputStream;
import java.util.function.Supplier;

@Tag("audio-player-element2")
@JsModule("./src/audio-player/audio-player-element2.ts")
public class AudioPlayer2 extends Component {


    private final transient Supplier<InputStream> inputStreamSupplier;

    public AudioPlayer2(Supplier<InputStream> inputStreamSupplier) {
        this.inputStreamSupplier = inputStreamSupplier;
    }

    @ClientCallable
    public String requestAudioStream() {
        AutoCloseInputStream autoCloseInputStream = new AutoCloseInputStream(inputStreamSupplier.get());
        StreamResource streamResource = new StreamResource(
                "audio_proxy_" + System.currentTimeMillis() + ".webm",
                () -> autoCloseInputStream);
        streamResource.setCacheTime(600000);
        streamResource.setContentType("application/octet-stream");
        getElement().setAttribute("streamResourceHandler", streamResource);
        return StreamResourceRegistry.getURI(streamResource).getPath();
    }
}

TypeScript (audio-player-element2.ts):

import {css, customElement, html, LitElement, property} from 'lit-element';
import '@vaadin/vaadin-icons/vaadin-icons.js';
import '@polymer/iron-icon/iron-icon.js';


interface AudioPlayer2 {
    requestAudioStream(): string;
}

@customElement('audio-player-element2')
export class AudioPlayerElement2 extends LitElement {

    declare $server: AudioPlayer2;

    @property()
    public audioPlayerInstance: HTMLAudioElement;
    @property({attribute: true})
    public playButtonIcon: string = "vaadin:play";
    @property()
    public audioLoaded: boolean = false;


    constructor() {
        super();
        this.audioPlayerInstance = new Audio();
        this.audioPlayerInstance.addEventListener("ended", () => this.onAudioEnded())
    }

    firstUpdated() {
        this.renderRoot.querySelector('.audio-container')?.appendChild(this.audioPlayerInstance);
    }


    render() {
        return html`
            <div class="audio-container" @click="${this.playAudio}}">
                <iron-icon class="play-pause-icon" icon="${this.playButtonIcon}"></iron-icon>
            </div>
        `;
    }

    playAudio() {
        if (this.audioLoaded) {
            this.audioPlayerInstance.play();
            this.playButtonIcon = "vaadin:stop";
        } else {
            // not sure how is right
            //let asyncSrcRequest = async () => await this.$server.requestAudioStream();
            let asyncSrcRequest = async () => this.$server.requestAudioStream();
            asyncSrcRequest().then((src) => {
                this.audioLoaded = true;
                this.audioPlayerInstance.src = src;
                this.audioPlayerInstance.play();
                this.playButtonIcon = "vaadin:stop";
            })
        }
    }

    onAudioEnded() {
        this.audioPlayerInstance.currentTime = 0;
        this.playButtonIcon = "vaadin:play";
    }

    static get styles() {
        return css`
                :host div.audio-container {
                    width: 50px;
                    border-radius: 7px;
                    padding: 3px;
                    display: inline-flex;
                    flex-direction: row;
                    flex-wrap: nowrap;
                    justify-content: flex-start;
                    box-shadow: inset 0 0 2px 1px #0087fd;
                    margin: 3px;
                    height: 15px;
                }

                :host div iron-icon.play-pause-icon {
                    width: 18px;
                    height: 18px;
                    display: contents;
                }
            `;
    }
}
lanmaster
  • 330
  • 2
  • 16