/* tslint:disable:max-line-length */ "use strict"; import React, { Component } from "react"; import ReactDOM from "react-dom"; import defaultOptions, { Options } from "./defaultOptions"; import Bridge from "./Bridge"; import EditableList from "./EditableList"; import getBridgeInfo from "../lib/getBridgeInfo"; const _ = browser.i18n.getMessage; // macOS styles browser.runtime.getPlatformInfo() .then(platformInfo => { if (platformInfo.os === "mac") { const link = document.createElement("link"); link.rel = "stylesheet"; link.href = "styles/mac.css"; document.head.appendChild(link); } }); const MATCH_PATTERN_REGEX = /^(?:(?:(\*|https?|ftp):\/\/((?:\*\.|[^\/\*])+)|(file):\/\/\/?(?:\*\.|[^\/\*])+)(\/.*)|)$/; function getInputValue (input: HTMLInputElement) { switch (input.type) { case "checkbox": return input.checked; case "number": return parseFloat(input.value); default: return input.value; } } interface OptionsAppState { hasLoaded: boolean; options: Options; bridgeInfo: any; platform: string; bridgeLoading: boolean; isFormValid: boolean; hasSaved: boolean; } class App extends Component<{}, OptionsAppState> { private form: HTMLFormElement; constructor (props: {}) { super(props); this.state = { hasLoaded: false , options: null , bridgeInfo: null , platform: null , bridgeLoading: true , isFormValid: true , hasSaved: false }; this.handleReset = this.handleReset.bind(this); this.handleFormSubmit = this.handleFormSubmit.bind(this); this.handleFormChange = this.handleFormChange.bind(this); this.handleInputChange = this.handleInputChange.bind(this); this.handleWhitelistChange = this.handleWhitelistChange.bind(this); this.getWhitelistItemPatternError = this.getWhitelistItemPatternError.bind(this); } async componentDidMount () { const { options } = await browser.storage.sync.get("options"); this.setState({ hasLoaded: true , options }); const bridgeInfo = await getBridgeInfo(); const { os } = await browser.runtime.getPlatformInfo(); this.setState({ bridgeInfo , platform: os , bridgeLoading: false }); } render () { if (!this.state.hasLoaded) { return; } return (
{ this.form = form; }} onSubmit={ this.handleFormSubmit } onChange={ this.handleFormChange }>

{ _("optionsMediaCategoryName") }

{ _("optionsMediaCategoryDescription") }

{ _("optionsLocalMediaCategoryName") }

{ _("optionsLocalMediaCategoryDescription") }

{ _("optionsMirroringCategoryName") }

{ _("optionsMirroringCategoryDescription") }

{ _("optionsUserAgentWhitelistCategoryName") }

{ _("optionsUserAgentWhitelistCategoryDescription") }

{ _("optionsUserAgentWhitelistContent") }
{ this.state.hasSaved && _("optionsSaved") }
); } /** * Set stored option values to current state */ private setStorage () { return browser.storage.sync.set({ options: this.state.options }); } private handleReset () { this.setState({ options: { ...defaultOptions } }); } private async handleFormSubmit (ev: React.FormEvent) { ev.preventDefault(); this.form.reportValidity(); try { const { options: oldOptions } = await browser.storage.sync.get("options"); await this.setStorage(); const { options } = await browser.storage.sync.get("options"); const alteredOptions = []; for (const [ key, val ] of Object.entries(options)) { const oldVal = oldOptions[key]; if (oldVal !== val) { alteredOptions.push(key); } } this.setState({ hasSaved: true }, () => { window.setTimeout(() => { this.setState({ hasSaved: false }); }, 1000); }); // Send update message / event browser.runtime.sendMessage({ subject: "optionsUpdated" , data: { alteredOptions } }); } catch (err) { console.error("Failed to save options"); } } private handleFormChange (ev: React.FormEvent) { ev.preventDefault(); this.setState({ isFormValid: this.form.checkValidity() }); } private handleInputChange (ev: React.ChangeEvent) { const { target } = ev; this.setState(({ options }) => { options[target.name] = getInputValue(target); return { options }; }); } private handleWhitelistChange (whitelist: string[]) { this.setState(({ options }) => { options.userAgentWhitelist = whitelist; return { options }; }); } private getWhitelistItemPatternError (info: string): string { return _("optionsUserAgentWhitelistInvalidMatchPattern", info); } private async updateBridgeInfo () { this.setState({ bridgeLoading: true }); const bridgeInfo = await getBridgeInfo(); this.setState({ bridgeInfo , bridgeLoading: false }); } } ReactDOM.render( , document.querySelector("#root"));