Files @ 485148ef5686
Branch filter:

Location: light9/web/live/Light9DeviceSettings.ts - annotation

drewp@bigasterisk.com
reformat
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
import debug from "debug";
import { css, html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators.js";
import { NamedNode } from "n3";
import { sortBy, uniq } from "underscore";
import { Patch } from "../patch";
import { getTopGraph } from "../RdfdbSyncedGraph";
import { SyncedGraph } from "../SyncedGraph";
import { Effect, newEffect } from "./Effect";
export { EditChoice } from "../EditChoice";
export { Light9DeviceControl as Light9LiveDeviceControl } from "./Light9DeviceControl";
const log = debug("settings");

@customElement("light9-device-settings")
export class Light9DeviceSettings extends LitElement {
  graph!: SyncedGraph;

  static styles = [
    css`
      :host {
        display: flex;
        flex-direction: column;
      }
      #preview {
        width: 100%;
      }
      #deviceControls {
        flex-grow: 1;
        position: relative;
        width: 100%;
        overflow-y: auto;
      }

      light9-device-control > div {
        break-inside: avoid-column;
      }
      light9-device-control {
        vertical-align: top;
      }
    `,
  ];

  render() {
    return html`
      <rdfdb-synced-graph></rdfdb-synced-graph>

      <h1>effect DeviceSettings</h1>

      <div id="save">
        <div>
          <button @click=${this.newEffect}>New effect</button>
          <edit-choice .uri=${this.currentEffect ? this.currentEffect.uri : null} @edited=${this.onEffectChoice2} rename></edit-choice>
          <button @click=${this.clearAll}>clear settings in this effect</button>
        </div>
      </div>

      <div id="deviceControls">
        ${this.devices.map(
          (device: NamedNode) => html`
            <light9-device-control .uri=${device} .effect=${this.currentEffect}> .graphToControls={this.graphToControls} </light9-device-control>
          `
        )}
      </div>
    `;
  }

  devices: Array<NamedNode> = [];
  @property() currentEffect: Effect | null = null;
  okToWriteUrl: boolean = false;

  constructor() {
    super();

    getTopGraph().then((g) => {
      this.graph = g;
      this.graph.runHandler(this.compile.bind(this), "findDevices");
      this.setEffectFromUrl();
    });
  }

  onEffectChoice2(ev: CustomEvent) {
    const uri = ev.detail.newValue as NamedNode;
    this.setCurrentEffect(uri);
  }
  setCurrentEffect(uri: NamedNode) {
    if (uri === null) {
      this.currentEffect = null;
      // todo: wipe the UI settings
    } else {
      this.currentEffect = new Effect(this.graph, uri);
    }
  }

  updated(changedProperties: PropertyValues<this>) {
    log("ctls udpated", changedProperties);
    if (changedProperties.has("currentEffect")) {
      log(`effectChoice to ${this.currentEffect?.uri?.value}`);
      this.writeToUrl(this.currentEffect?.uri);
    }
    // this.graphToControls?.debugDump();
  }

  // Note that this doesn't fetch setting values, so it only should get rerun
  // upon (rarer) changes to the devices etc. todo: make that be true
  private compile(patch?: Patch) {
    const U = this.graph.U();
    // if (patch && !patchContainsPreds(patch, [U("rdf:type")])) {
    //   return;
    // }

    this.devices = [];
    let classes = this.graph.subjects(U("rdf:type"), U(":DeviceClass"));
    log(`found ${classes.length} device classes`);
    uniq(sortBy(classes, "value"), true).forEach((dc) => {
      sortBy(this.graph.subjects(U("rdf:type"), dc), "value").forEach((dev) => {
        this.devices.push(dev as NamedNode);
      });
    });
    this.requestUpdate();
  }

  setEffectFromUrl() {
    // not a continuous bidi link between url and effect; it only reads
    // the url when the page loads.
    const effect = new URL(window.location.href).searchParams.get("effect");
    if (effect != null) {
      this.currentEffect = new Effect(this.graph, this.graph.Uri(effect));
    }
    this.okToWriteUrl = true;
  }

  writeToUrl(effect: NamedNode | undefined) {
    const effectStr = effect ? this.graph.shorten(effect) : "";
    if (!this.okToWriteUrl) {
      return;
    }
    const u = new URL(window.location.href);
    if ((u.searchParams.get("effect") || "") === effectStr) {
      return;
    }
    u.searchParams.set("effect", effectStr); // this escapes : and / and i wish it didn't
    window.history.replaceState({}, "", u.href);
    log("wrote new url", u.href);
  }

  newEffect() {
    this.setCurrentEffect(newEffect(this.graph));
  }

  clearAll() {
    this.currentEffect?.clearAllSettings()
  }
}