darthtrevino/savey-wavey

View on GitHub
src/feedback/SaveStatusIndicator.ts

Summary

Maintainability
B
4 hrs
Test Coverage
import {ISimpleResultHandler} from "./interfaces";
import { IActiveItemListener } from "../interfaces";
const { Disposable } = require("atom");
const STATUS_UNKNOWN = "save-status-unknown";
const STATUS_SUCCESS = "save-status-success";
const STATUS_FAIL = "save-status-failure";

// TODO: LRU-ify this thing
const saveStatusCache = {};

class SaveStatusIndicator extends HTMLElement implements ISimpleResultHandler {
    public activeItemListener: IActiveItemListener;
    private clickSubscription: AtomCore.Disposable;
    private saveStatusIcon: HTMLSpanElement;
    private clickHandlers: (() => void)[];

    public initialize() {
        this.clickHandlers = [];
        this.classList.add("save-status-indicator");
        this.createSaveStatusIcon();
        this.activeItemListener.subscribe(this.onActiveItemChanged.bind(this));
    }

    public onSuccess(file: string) {
        saveStatusCache[file] = true;
        if (file === this.activeItemPath) {
            this.saveStatusIcon.classList.remove(STATUS_UNKNOWN, STATUS_FAIL);
            this.saveStatusIcon.classList.add(STATUS_SUCCESS);
        }
    }

    public onFailure(file: string) {
        saveStatusCache[file] = false;
        if (file === this.activeItemPath) {
            this.saveStatusIcon.classList.remove(STATUS_UNKNOWN, STATUS_SUCCESS);
            this.saveStatusIcon.classList.add(STATUS_FAIL);
        }
    }

    public destroy() {
        this.clickSubscription.dispose();
    }

    public registerOnClickHandler(handler) {
        this.clickHandlers.push(handler);
    }

    private get activeItemPath(): string {
        return this.activeItemListener ? this.activeItemListener.activeItemPath : null;
    }

    private onActiveItemChanged(file) {
        this.saveStatusIcon.classList.remove(STATUS_FAIL, STATUS_SUCCESS, STATUS_UNKNOWN);
        if (!saveStatusCache.hasOwnProperty(file)) {
            this.saveStatusIcon.classList.add(STATUS_UNKNOWN);
        } else if (saveStatusCache[file]) {
            this.saveStatusIcon.classList.add(STATUS_SUCCESS);
        } else {
            this.saveStatusIcon.classList.add(STATUS_FAIL);
        }
    }

    private createSaveStatusIcon() {
        const icon = document.createElement("span");
        icon.classList.add("icon", "icon-checklist", STATUS_UNKNOWN);
        this.appendChild(icon);
        this.saveStatusIcon = icon;

        const clickHandler = this.onIconClicked.bind(this);
        icon.addEventListener("click", clickHandler);
        this.clickSubscription = new Disposable(() => icon.removeEventListener("click", clickHandler));
    }

    private onIconClicked() {
        this.clickHandlers.forEach(handler => handler());
    }
}

const elementType = document["registerElement"]("save-status-indicator", { prototype: SaveStatusIndicator.prototype, extends: "div" });
export default elementType;