mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-10 01:29:58 +00:00
Implement options page
This commit is contained in:
44
ext/src/options/index.css
Normal file
44
ext/src/options/index.css
Normal file
@@ -0,0 +1,44 @@
|
||||
.category {
|
||||
display: grid;
|
||||
grid-template-columns: min-content min-content;
|
||||
grid-column-gap: 20px;
|
||||
grid-row-gap: 5px;
|
||||
}
|
||||
.category-name {}
|
||||
.category-description {
|
||||
color: graytext;
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.option {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.option-label {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.option > input {
|
||||
align-self: center;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
#form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
align-self: flex-end;
|
||||
margin-block-start: 5px;
|
||||
}
|
||||
|
||||
#buttons > :not(:last-child) {
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
*:invalid {
|
||||
box-shadow: 0 0 1.5px 1px red;
|
||||
}
|
||||
11
ext/src/options/index.html
Normal file
11
ext/src/options/index.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<script src="bundle.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
141
ext/src/options/index.jsx
Normal file
141
ext/src/options/index.jsx
Normal file
@@ -0,0 +1,141 @@
|
||||
"use strict";
|
||||
|
||||
import React, { Component } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
|
||||
const _ = browser.i18n.getMessage;
|
||||
|
||||
|
||||
class OptionsApp extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isFormValid: true
|
||||
};
|
||||
|
||||
this.handleFormSubmit = this.handleFormSubmit.bind(this);
|
||||
this.handleFormChange = this.handleFormChange.bind(this);
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stored option values to current state
|
||||
*/
|
||||
setStorage () {
|
||||
return browser.storage.sync.set({
|
||||
options: {
|
||||
option_localMediaEnabled: this.state.option_localMediaEnabled
|
||||
, option_localMediaServerPort: this.state.option_localMediaServerPort
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current options state from storage and set initial
|
||||
*/
|
||||
async componentDidMount () {
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
if (options) {
|
||||
this.setState({
|
||||
...options
|
||||
, isFormValid: this.form.checkValidity()
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
await this.setStorage();
|
||||
} catch (err) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async handleFormSubmit (ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
this.form.reportValidity();
|
||||
|
||||
try {
|
||||
await this.setStorage();
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
handleFormChange () {
|
||||
this.setState({
|
||||
isFormValid: this.form.checkValidity()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
handleInputChange (ev) {
|
||||
const val = do {
|
||||
if (ev.target.type === "checkbox") {
|
||||
ev.target.checked;
|
||||
} else if (ev.target.type === "number") {
|
||||
parseInt(ev.target.value);
|
||||
} else {
|
||||
ev.target.value;
|
||||
}
|
||||
};
|
||||
|
||||
console.log(ev.target.name);
|
||||
|
||||
this.setState({
|
||||
[ ev.target.name ]: val
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<form id="form" ref={ form => { this.form = form; }}
|
||||
onSubmit={ this.handleFormSubmit }
|
||||
onChange={ this.handleFormChange }>
|
||||
<fieldset className="category">
|
||||
<legend className="category-name">
|
||||
{ _("options_category_localMedia") }
|
||||
</legend>
|
||||
<p className="category-description">
|
||||
{ _("options_category_localMedia_description") }
|
||||
</p>
|
||||
|
||||
<label className="option">
|
||||
<div className="option-label">
|
||||
{ _("options_option_localMediaEnabled") }
|
||||
</div>
|
||||
<input name="option_localMediaEnabled"
|
||||
type="checkbox"
|
||||
checked={ this.state.option_localMediaEnabled }
|
||||
onChange={ this.handleInputChange } />
|
||||
</label>
|
||||
|
||||
<label className="option">
|
||||
<div className="option-label">
|
||||
{ _("options_option_localMediaServerPort") }
|
||||
</div>
|
||||
<input name="option_localMediaServerPort"
|
||||
type="number"
|
||||
required
|
||||
min="1025"
|
||||
max="65535"
|
||||
value={ this.state.option_localMediaServerPort }
|
||||
onChange={ this.handleInputChange } />
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div id="buttons">
|
||||
<button type="submit"
|
||||
disabled={ !this.state.isFormValid }>
|
||||
{ _("options_submit") }
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ReactDOM.render(
|
||||
<OptionsApp />
|
||||
, document.querySelector("#root"));
|
||||
Reference in New Issue
Block a user