//@ts-ignore import { MDCRipple } from "@material/ripple"; //@ts-ignore import { MDCTextField } from "@material/textfield"; //@ts-ignore import { MDCLinearProgress } from "@material/linear-progress"; import * as React from "react"; import * as ReactDOM from "react-dom"; import { RegisteredServer } from "./app"; // tslint:disable-next-line:no-any declare var WebSettings: any; interface AuthedUser { readonly username: string; } export class Main extends React.Component { private webview: HTMLWebViewElement | undefined; public constructor(props: void) { super(props); this.state = { view: "servers", loading: false, }; } public componentDidMount(): void { window.addEventListener("message", (event) => { if (event.data === "back") { if (this.webview) { this.webview.classList.remove("active"); } } if (event.data === "loaded") { if (this.webview) { // this.setState({ loading: false }); // this.webview.classList.add("active"); } } }); if (this.webview) { this.webview.addEventListener("error", (event) => { console.error(event); }); this.webview.addEventListener("loadstart", (event) => { this.setState({ loading: true }); }); this.webview.addEventListener("loadstop", (event) => { this.setState({ loading: false }); this.webview!.classList.add("active"); // tslint:disable-next-line:no-any const cw = (this.webview as any).contentWindow as Window; cw.postMessage("app", "*"); }); } } public render(): JSX.Element { return (
{((): JSX.Element => { switch (this.state.view) { case "servers": return ( { if (this.webview) { this.webview.setAttribute("src", server.hostname); } }} onAddServer={() => this.setState({ view: "add-server" })} loading={this.state.loading} /> ); case "add-server": return (
Add server
); } })()}
this.webview = wv}>
); } } export class AddServer extends React.Component { public render(): JSX.Element { return (

Add Server

Something about what you can do once you add your own server. A link to setup guides for this would be great as well.



); } } export class Servers extends React.Component<{ readonly user?: AuthedUser; readonly servers: ReadonlyArray; readonly onSelect: (server: RegisteredServer) => void; readonly onAddServer: () => void; readonly loading: boolean; }, { readonly refreshing: boolean; }> { // tslint:disable-next-line:no-any public constructor(props: any) { super(props); this.state = { refreshing: false, }; } public render(): JSX.Element { return (

Servers

this.doRefresh()} className={this.state.refreshing ? "refreshing" : ""} width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
Status
Server Name
Hostname
Details
{/* Used for continue/launch buttons */}
{/* Used for logout and delete buttons */}
{ if (d) new MDCLinearProgress(d)}}>
{this.props.servers.map((server, i) => { return ( this.props.onSelect(server)} /> ); })}
); } private doRefresh(): void { if (this.state.refreshing) { return; } this.setState({ refreshing: true, }, () => { setTimeout(() => { this.setState({ refreshing: false, }); }, 1500); }); } } interface ServerProps { readonly user?: AuthedUser; readonly server: RegisteredServer; readonly onSelect: () => void; } export class Server extends React.Component { // tslint:disable-next-line:no-any public constructor(props: ServerProps) { super(props); this.state = { status: props.server.host === "coder" ? "Online" : "Checking", version: "", }; } public componentWillMount(): void { if (this.props.server.host !== "self") { return; } const xhr = new XMLHttpRequest(); xhr.open("GET", this.props.server.hostname); xhr.addEventListener("error", (err) => { this.setState({ status: "Offline", }); }); xhr.addEventListener("loadend", () => { if (xhr.status === 200) { this.setState({ status: "Online", version: process.env.VERSION, }); } else { this.setState({ status: "Offline", }); } }); xhr.send(); } public render(): JSX.Element { return ( <>
{((): JSX.Element => { switch (this.state.status) { case "Offline": return ( ); case "Online": return ( ); case "Checking": return ( ); default: throw new Error("unsupported status"); } })()} {this.state.status}
{this.props.server.host === "coder" ? ( ) : this.props.server.name}
{this.props.server.hostname}
{this.props.server.host === "coder" && this.props.user ? `Logged in as ${this.props.user.username}` : this.state.version}
{this.props.server.host === "coder" ? ( ) : ( )}
); } private get extraClasses(): string { return this.props.server.host === "coder" ? "dark" : ""; } } export class Input extends React.Component<{ readonly label: string; readonly id: string; readonly type?: string; }> { private wrapper: HTMLDivElement | undefined; public componentDidMount(): void { if (this.wrapper) { const textInput = new MDCTextField(this.wrapper); } } public render(): JSX.Element { return (
this.wrapper = i}>
); } } export class Button extends React.Component<{ readonly type: "outlined" | "unelevated"; readonly className?: string; readonly onClick?: () => void; }> { private button: HTMLButtonElement | undefined; public componentDidMount(): void { if (this.button) { const b = new MDCRipple(this.button); } } public render(): JSX.Element { return ( ); } } export class Tooltip extends React.Component<{ readonly message: string; }> { public componentDidMount(): void { Object.keys(this.refs).forEach((ref) => { const el = this.refs[ref]; if (el) { const element = ReactDOM.findDOMNode(el); if (element) { const te = document.createElement("div"); te.className = "md-tooltip-content"; te.innerHTML = this.props.message; element.appendChild(te); (element as HTMLElement).classList.add("md-tooltip"); } } }); } public render(): JSX.Element { return ( <> {React.Children.map(this.props.children, (element, idx) => { return React.cloneElement(element as any, { ref: idx }); })} ); } } export class Ripple extends React.Component<{ readonly className?: string; }> { public componentDidMount(): void { Object.keys(this.refs).forEach((ref) => { const el = this.refs[ref]; if (el) { const element = ReactDOM.findDOMNode(el); if (element) { (element as HTMLElement).classList.add("mdc-ripple-surface"); (element as HTMLElement).setAttribute("data-mdc-ripple-is-unbounded", ""); const r = new MDCRipple(element); } } }); } public render(): JSX.Element { return ( <> {React.Children.map(this.props.children, (element, idx) => { return React.cloneElement(element as any, { ref: idx }); })} ); } } export class Logo extends React.Component { public render(): JSX.Element { return ( ); } } // const $ = (tagName: K, className?: string, content?: string): HTMLElementTagNameMap[K] => { // const el = document.createElement(tagName); // if (className) { // el.className = className; // } // if (content) { // el.innerText = content; // } // return el; // }; // const createInput = (id: string, labelName: string, type: string = "text"): HTMLDivElement => { // //
// // // // // //
// //
// //
// // // //
// //
// //
// const wrapper = $("div", "mdc-text-field mdc-text-field--outlined"); // const input = $("input", "mdc-text-field__input"); // input.type = type; // input.id = id; // wrapper.appendChild(input); // const notchedOutline = $("div", "mdc-notched-outline"); // notchedOutline.appendChild($("div", "mdc-notched-outline__leading")); // const notch = $("div", "mdc-notched-outline__notch"); // const label = $("label", "mdc-floating-label", labelName); // label.setAttribute("for", id); // notch.appendChild(label); // notchedOutline.appendChild(notch); // wrapper.appendChild(notchedOutline); // wrapper.appendChild($("div", "mdc-notched-outline__trailing")); // const field = new MDCTextField(wrapper); // return wrapper; // }; // export const createCoderLogin = (parentNode: HTMLElement): void => { // parentNode.appendChild($("h1", "header", "Login with Coder")); // parentNode.appendChild(createInput("username", "Username")); // parentNode.appendChild($("br")); // parentNode.appendChild($("br")); // parentNode.appendChild(createInput("password", "Password", "password")); // };