WiFi Channel Settings.
This commit is contained in:
+10
-2
@@ -5,20 +5,22 @@ find_program(NPM_COMMAND npm)
|
||||
|
||||
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(BUILD_REACT "echo")
|
||||
set(BUILD_REACT_ARGS Skipping react debug build)
|
||||
else()
|
||||
set(BUILD_REACT ${NPM_COMMAND})
|
||||
set(BUILD_REACT_ARGS run build)
|
||||
endif()
|
||||
|
||||
set (BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build)
|
||||
message(STATUS "React Build...")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${BUILD_DIRECTORY}/index.html
|
||||
COMMAND ${BUILD_REACT}
|
||||
ARGS run build
|
||||
ARGS ${BUILD_REACT_ARGS}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/react
|
||||
|
||||
DEPENDS
|
||||
src/WifiChannel.tsx
|
||||
src/JackServerSettingsDialog.tsx
|
||||
src/JackServerSettings.tsx
|
||||
|
||||
@@ -74,7 +76,13 @@ add_custom_command(
|
||||
src/Utility.tsx
|
||||
src/VuMeter.tsx
|
||||
src/PluginPreset.tsx
|
||||
src/XxxSnippet.tsx
|
||||
src/WifiConfigSettings.tsx
|
||||
src/WifiConfigDialog.tsx
|
||||
src/NoChangePassword.tsx
|
||||
src/XxxSnippet.tsx
|
||||
|
||||
public/iso_codes.json
|
||||
public/logo512.png
|
||||
public/index.html
|
||||
public/manifest.json
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "BUILD_PATH='../../build/react/src/build' react-scripts build",
|
||||
"build": "BUILD_PATH='../build/react/build' react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
{
|
||||
"AF": "Afghanistan",
|
||||
"AX": "Aland Islands",
|
||||
"AL": "Albania",
|
||||
"DZ": "Algeria",
|
||||
"AS": "American Samoa",
|
||||
"AD": "Andorra",
|
||||
"AO": "Angola",
|
||||
"AI": "Anguilla",
|
||||
"AQ": "Antarctica",
|
||||
"AG": "Antigua And Barbuda",
|
||||
"AR": "Argentina",
|
||||
"AM": "Armenia",
|
||||
"AW": "Aruba",
|
||||
"AU": "Australia",
|
||||
"AT": "Austria",
|
||||
"AZ": "Azerbaijan",
|
||||
"BS": "Bahamas",
|
||||
"BH": "Bahrain",
|
||||
"BD": "Bangladesh",
|
||||
"BB": "Barbados",
|
||||
"BY": "Belarus",
|
||||
"BE": "Belgium",
|
||||
"BZ": "Belize",
|
||||
"BJ": "Benin",
|
||||
"BM": "Bermuda",
|
||||
"BT": "Bhutan",
|
||||
"BO": "Bolivia",
|
||||
"BA": "Bosnia And Herzegovina",
|
||||
"BW": "Botswana",
|
||||
"BV": "Bouvet Island",
|
||||
"BR": "Brazil",
|
||||
"IO": "British Indian Ocean Territory",
|
||||
"BN": "Brunei Darussalam",
|
||||
"BG": "Bulgaria",
|
||||
"BF": "Burkina Faso",
|
||||
"BI": "Burundi",
|
||||
"KH": "Cambodia",
|
||||
"CM": "Cameroon",
|
||||
"CA": "Canada",
|
||||
"CV": "Cape Verde",
|
||||
"KY": "Cayman Islands",
|
||||
"CF": "Central African Republic",
|
||||
"TD": "Chad",
|
||||
"CL": "Chile",
|
||||
"CN": "China",
|
||||
"CX": "Christmas Island",
|
||||
"CC": "Cocos (Keeling) Islands",
|
||||
"CO": "Colombia",
|
||||
"KM": "Comoros",
|
||||
"CG": "Congo",
|
||||
"CD": "Congo, Democratic Republic",
|
||||
"CK": "Cook Islands",
|
||||
"CR": "Costa Rica",
|
||||
"CI": "Cote D\"Ivoire",
|
||||
"HR": "Croatia",
|
||||
"CU": "Cuba",
|
||||
"CY": "Cyprus",
|
||||
"CZ": "Czech Republic",
|
||||
"DK": "Denmark",
|
||||
"DJ": "Djibouti",
|
||||
"DM": "Dominica",
|
||||
"DO": "Dominican Republic",
|
||||
"EC": "Ecuador",
|
||||
"EG": "Egypt",
|
||||
"SV": "El Salvador",
|
||||
"GQ": "Equatorial Guinea",
|
||||
"ER": "Eritrea",
|
||||
"EE": "Estonia",
|
||||
"ET": "Ethiopia",
|
||||
"FK": "Falkland Islands (Malvinas)",
|
||||
"FO": "Faroe Islands",
|
||||
"FJ": "Fiji",
|
||||
"FI": "Finland",
|
||||
"FR": "France",
|
||||
"GF": "French Guiana",
|
||||
"PF": "French Polynesia",
|
||||
"TF": "French Southern Territories",
|
||||
"GA": "Gabon",
|
||||
"GM": "Gambia",
|
||||
"GE": "Georgia",
|
||||
"DE": "Germany",
|
||||
"GH": "Ghana",
|
||||
"GI": "Gibraltar",
|
||||
"GR": "Greece",
|
||||
"GL": "Greenland",
|
||||
"GD": "Grenada",
|
||||
"GP": "Guadeloupe",
|
||||
"GU": "Guam",
|
||||
"GT": "Guatemala",
|
||||
"GG": "Guernsey",
|
||||
"GN": "Guinea",
|
||||
"GW": "Guinea-Bissau",
|
||||
"GY": "Guyana",
|
||||
"HT": "Haiti",
|
||||
"HM": "Heard Island & Mcdonald Islands",
|
||||
"VA": "Holy See (Vatican City State)",
|
||||
"HN": "Honduras",
|
||||
"HK": "Hong Kong",
|
||||
"HU": "Hungary",
|
||||
"IS": "Iceland",
|
||||
"IN": "India",
|
||||
"ID": "Indonesia",
|
||||
"IR": "Iran, Islamic Republic Of",
|
||||
"IQ": "Iraq",
|
||||
"IE": "Ireland",
|
||||
"IM": "Isle Of Man",
|
||||
"IL": "Israel",
|
||||
"IT": "Italy",
|
||||
"JM": "Jamaica",
|
||||
"JP": "Japan",
|
||||
"JE": "Jersey",
|
||||
"JO": "Jordan",
|
||||
"KZ": "Kazakhstan",
|
||||
"KE": "Kenya",
|
||||
"KI": "Kiribati",
|
||||
"KR": "Korea",
|
||||
"KP": "North Korea",
|
||||
"KW": "Kuwait",
|
||||
"KG": "Kyrgyzstan",
|
||||
"LA": "Lao People\"s Democratic Republic",
|
||||
"LV": "Latvia",
|
||||
"LB": "Lebanon",
|
||||
"LS": "Lesotho",
|
||||
"LR": "Liberia",
|
||||
"LY": "Libyan Arab Jamahiriya",
|
||||
"LI": "Liechtenstein",
|
||||
"LT": "Lithuania",
|
||||
"LU": "Luxembourg",
|
||||
"MO": "Macao",
|
||||
"MK": "Macedonia",
|
||||
"MG": "Madagascar",
|
||||
"MW": "Malawi",
|
||||
"MY": "Malaysia",
|
||||
"MV": "Maldives",
|
||||
"ML": "Mali",
|
||||
"MT": "Malta",
|
||||
"MH": "Marshall Islands",
|
||||
"MQ": "Martinique",
|
||||
"MR": "Mauritania",
|
||||
"MU": "Mauritius",
|
||||
"YT": "Mayotte",
|
||||
"MX": "Mexico",
|
||||
"FM": "Micronesia, Federated States Of",
|
||||
"MD": "Moldova",
|
||||
"MC": "Monaco",
|
||||
"MN": "Mongolia",
|
||||
"ME": "Montenegro",
|
||||
"MS": "Montserrat",
|
||||
"MA": "Morocco",
|
||||
"MZ": "Mozambique",
|
||||
"MM": "Myanmar",
|
||||
"NA": "Namibia",
|
||||
"NR": "Nauru",
|
||||
"NP": "Nepal",
|
||||
"NL": "Netherlands",
|
||||
"AN": "Netherlands Antilles",
|
||||
"NC": "New Caledonia",
|
||||
"NZ": "New Zealand",
|
||||
"NI": "Nicaragua",
|
||||
"NE": "Niger",
|
||||
"NG": "Nigeria",
|
||||
"NU": "Niue",
|
||||
"NF": "Norfolk Island",
|
||||
"MP": "Northern Mariana Islands",
|
||||
"NO": "Norway",
|
||||
"OM": "Oman",
|
||||
"PK": "Pakistan",
|
||||
"PW": "Palau",
|
||||
"PS": "Palestinian Territory, Occupied",
|
||||
"PA": "Panama",
|
||||
"PG": "Papua New Guinea",
|
||||
"PY": "Paraguay",
|
||||
"PE": "Peru",
|
||||
"PH": "Philippines",
|
||||
"PN": "Pitcairn",
|
||||
"PL": "Poland",
|
||||
"PT": "Portugal",
|
||||
"PR": "Puerto Rico",
|
||||
"QA": "Qatar",
|
||||
"RE": "Reunion",
|
||||
"RO": "Romania",
|
||||
"RU": "Russian Federation",
|
||||
"RW": "Rwanda",
|
||||
"BL": "Saint Barthelemy",
|
||||
"SH": "Saint Helena",
|
||||
"KN": "Saint Kitts And Nevis",
|
||||
"LC": "Saint Lucia",
|
||||
"MF": "Saint Martin",
|
||||
"PM": "Saint Pierre And Miquelon",
|
||||
"VC": "Saint Vincent And Grenadines",
|
||||
"WS": "Samoa",
|
||||
"SM": "San Marino",
|
||||
"ST": "Sao Tome And Principe",
|
||||
"SA": "Saudi Arabia",
|
||||
"SN": "Senegal",
|
||||
"RS": "Serbia",
|
||||
"SC": "Seychelles",
|
||||
"SL": "Sierra Leone",
|
||||
"SG": "Singapore",
|
||||
"SK": "Slovakia",
|
||||
"SI": "Slovenia",
|
||||
"SB": "Solomon Islands",
|
||||
"SO": "Somalia",
|
||||
"ZA": "South Africa",
|
||||
"GS": "South Georgia And Sandwich Isl.",
|
||||
"ES": "Spain",
|
||||
"LK": "Sri Lanka",
|
||||
"SD": "Sudan",
|
||||
"SR": "Suriname",
|
||||
"SJ": "Svalbard And Jan Mayen",
|
||||
"SZ": "Swaziland",
|
||||
"SE": "Sweden",
|
||||
"CH": "Switzerland",
|
||||
"SY": "Syrian Arab Republic",
|
||||
"TW": "Taiwan",
|
||||
"TJ": "Tajikistan",
|
||||
"TZ": "Tanzania",
|
||||
"TH": "Thailand",
|
||||
"TL": "Timor-Leste",
|
||||
"TG": "Togo",
|
||||
"TK": "Tokelau",
|
||||
"TO": "Tonga",
|
||||
"TT": "Trinidad And Tobago",
|
||||
"TN": "Tunisia",
|
||||
"TR": "Turkey",
|
||||
"TM": "Turkmenistan",
|
||||
"TC": "Turks And Caicos Islands",
|
||||
"TV": "Tuvalu",
|
||||
"UG": "Uganda",
|
||||
"UA": "Ukraine",
|
||||
"AE": "United Arab Emirates",
|
||||
"GB": "United Kingdom",
|
||||
"US": "United States",
|
||||
"UM": "United States Outlying Islands",
|
||||
"UY": "Uruguay",
|
||||
"UZ": "Uzbekistan",
|
||||
"VU": "Vanuatu",
|
||||
"VE": "Venezuela",
|
||||
"VN": "Vietnam",
|
||||
"VG": "Virgin Islands, British",
|
||||
"VI": "Virgin Islands, U.S.",
|
||||
"WF": "Wallis And Futuna",
|
||||
"EH": "Western Sahara",
|
||||
"YE": "Yemen",
|
||||
"ZM": "Zambia",
|
||||
"ZW": "Zimbabwe"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"socket_server_port": 80,
|
||||
"socket_server_port": 8080,
|
||||
"socket_server_address": "*",
|
||||
|
||||
"max_upload_size": 1048576,
|
||||
|
||||
+1
-1
@@ -646,7 +646,7 @@ const App = withStyles(appStyles)(class extends ResizeResponsiveComponent<AppPro
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<TemporaryDrawer position='left' title="piddle"
|
||||
<TemporaryDrawer position='left' title="PiPedal"
|
||||
is_open={this.state.isDrawerOpen} onClose={() => { this.hideDrawer(); }} >
|
||||
<List subheader={
|
||||
<ListSubheader component="div" id="nested-list-subheader">Banks</ListSubheader>
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import React from 'react';
|
||||
|
||||
import Dialog, {DialogProps} from '@material-ui/core/Dialog';
|
||||
|
||||
|
||||
interface DialogExProps extends DialogProps {
|
||||
tag: string;
|
||||
}
|
||||
|
||||
interface DialogExState {
|
||||
|
||||
}
|
||||
|
||||
class DialogEx extends React.Component<DialogExProps,DialogExState> {
|
||||
constructor(props: DialogExProps)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
};
|
||||
this.handlePopState = this.handlePopState.bind(this);
|
||||
|
||||
}
|
||||
|
||||
mounted: boolean = false;
|
||||
|
||||
hasHooks: boolean = false;
|
||||
|
||||
stateWasPopped: boolean = false;
|
||||
handlePopState(e: any): any {
|
||||
this.stateWasPopped = true;
|
||||
let shouldClose = (!e.state || !e.state[this.props.tag]);
|
||||
if (shouldClose)
|
||||
{
|
||||
if (this.props.onClose)
|
||||
{
|
||||
this.props.onClose(e,"backdropClick");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateHooks() : void {
|
||||
let wantHooks = this.mounted && this.props.open;
|
||||
if (wantHooks !== this.hasHooks)
|
||||
{
|
||||
this.hasHooks = wantHooks;
|
||||
|
||||
if (this.hasHooks)
|
||||
{
|
||||
this.stateWasPopped = false;
|
||||
window.addEventListener("popstate",this.handlePopState);
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
let state = history.state;
|
||||
if (!state)
|
||||
{
|
||||
state = {};
|
||||
}
|
||||
state[this.props.tag] = true;
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
history.pushState(
|
||||
state,
|
||||
"",
|
||||
"#" + this.props.tag
|
||||
);
|
||||
} else {
|
||||
window.removeEventListener("popstate",this.handlePopState);
|
||||
if (!this.stateWasPopped)
|
||||
{
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
onWindowSizeChanged(width: number, height: number): void
|
||||
{
|
||||
this.setState({fullScreen: height < 200})
|
||||
}
|
||||
|
||||
|
||||
componentDidMount()
|
||||
{
|
||||
if (super.componentDidMount)
|
||||
{
|
||||
super.componentDidMount();
|
||||
}
|
||||
this.mounted = true;
|
||||
this.updateHooks();
|
||||
}
|
||||
componentWillUnmount()
|
||||
{
|
||||
if (super.componentWillUnmount)
|
||||
{
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
this.mounted = false;
|
||||
this.updateHooks();
|
||||
}
|
||||
|
||||
componentDidUpdate()
|
||||
{
|
||||
this.updateHooks();
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let { tag, ...extra} = this.props;
|
||||
return (
|
||||
<Dialog {...extra}>
|
||||
{this.props.children}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default DialogEx;
|
||||
@@ -187,7 +187,7 @@ export const MidiBindingDialog =
|
||||
this.updateHooks();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
super.componentDidMount();
|
||||
super.componentWillUnmount();
|
||||
|
||||
this.mounted = false;
|
||||
this.updateHooks();
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
import React from 'react';
|
||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import FormHelperText from '@material-ui/core/FormHelperText';
|
||||
import InputLabel from '@material-ui/core/InputLabel';
|
||||
import Input from '@material-ui/core/Input';
|
||||
|
||||
import Visibility from '@material-ui/icons/Visibility';
|
||||
import VisibilityOff from '@material-ui/icons/VisibilityOff';
|
||||
|
||||
|
||||
|
||||
interface NoChangePasswordProps {
|
||||
hasPassword: boolean;
|
||||
label: string;
|
||||
defaultValue: string;
|
||||
onPasswordChange: (text: string) => void;
|
||||
disabled?: boolean;
|
||||
helperText?: string;
|
||||
error?: boolean;
|
||||
};
|
||||
|
||||
interface NoChangePasswordState {
|
||||
focused: boolean;
|
||||
passwordText: string;
|
||||
showPassword: boolean;
|
||||
};
|
||||
|
||||
class NoChangePassword extends React.Component<NoChangePasswordProps, NoChangePasswordState> {
|
||||
refText: React.Ref<HTMLInputElement | HTMLTextAreaElement>;
|
||||
|
||||
constructor(props: NoChangePasswordProps) {
|
||||
super(props);
|
||||
this.refText = React.createRef();
|
||||
this.state = {
|
||||
focused: false,
|
||||
showPassword: false,
|
||||
passwordText: this.props.defaultValue as string
|
||||
};
|
||||
}
|
||||
|
||||
handleShowPassword() {
|
||||
this.setState({
|
||||
showPassword: !this.state.showPassword
|
||||
});
|
||||
}
|
||||
handleChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
|
||||
this.textChanged = true;
|
||||
this.props.onPasswordChange(e.target.value);
|
||||
}
|
||||
|
||||
textChanged: boolean = false;
|
||||
handleFocus(e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) {
|
||||
console.log("onFocus");
|
||||
if (!this.state.focused) {
|
||||
this.textChanged = false;
|
||||
e.target.value = this.state.passwordText;
|
||||
}
|
||||
e.currentTarget.removeAttribute("readonly");
|
||||
this.setState({ focused: true });
|
||||
}
|
||||
handleBlur(e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) {
|
||||
console.log("onBlur");
|
||||
let text = e.target.value as string;
|
||||
this.setState({ focused: false, passwordText: text });
|
||||
this.props.onPasswordChange(e.target.value);
|
||||
this.textChanged = false;
|
||||
if (text.length === 0 && this.props.hasPassword)
|
||||
{
|
||||
e.target.value = "(Unchanged)";
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("Render focus: " + this.state.focused)
|
||||
let showUnchanged = (this.state.passwordText.length === 0) && this.props.hasPassword && (!this.state.focused);
|
||||
let thisDefaultValue = showUnchanged ? "(Unchanged)" : this.props.defaultValue;
|
||||
|
||||
let isText = showUnchanged || this.state.showPassword;
|
||||
|
||||
|
||||
return (
|
||||
<FormControl disabled={this.props.disabled} fullWidth error={this.props.error} >
|
||||
<InputLabel htmlFor="standard-adornment-password">{this.props.label}</InputLabel>
|
||||
<Input
|
||||
fullWidth
|
||||
color="primary"
|
||||
spellCheck="false"
|
||||
autoComplete="off"
|
||||
readOnly
|
||||
id="standard-adornment-password"
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
value={thisDefaultValue}
|
||||
onFocus={(e) => this.handleFocus(e)}
|
||||
onBlur={(e) => this.handleBlur(e)}
|
||||
type={isText ? 'text' : 'password'}
|
||||
style={ { color: showUnchanged? '#888': '#000'} }
|
||||
|
||||
endAdornment={
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle password visibility"
|
||||
onClick={(e) => this.handleShowPassword()}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
>
|
||||
{this.state.showPassword ? <Visibility /> : <VisibilityOff />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
}
|
||||
/>
|
||||
<FormHelperText >{ this.props.helperText}</FormHelperText>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default NoChangePassword;
|
||||
@@ -117,7 +117,7 @@ const pedalBoardStyles = (theme: Theme) => createStyles({
|
||||
marginBottom: (CELL_HEIGHT - FRAME_SIZE) / 2,
|
||||
width: FRAME_SIZE,
|
||||
height: FRAME_SIZE,
|
||||
border: "1pt black solid",
|
||||
border: "1pt #666 solid",
|
||||
borderRadius: 6
|
||||
},
|
||||
pedalIcon: {
|
||||
|
||||
+108
-6
@@ -13,6 +13,8 @@ import JackHostStatus from './JackHostStatus';
|
||||
import JackServerSettings from './JackServerSettings';
|
||||
import MidiBinding from './MidiBinding';
|
||||
import PluginPreset from './PluginPreset';
|
||||
import WifiConfigSettings from './WifiConfigSettings';
|
||||
import WifiChannel from './WifiChannel';
|
||||
|
||||
|
||||
export enum State {
|
||||
@@ -235,6 +237,7 @@ interface ControlChangedBody {
|
||||
|
||||
export interface PiPedalModel {
|
||||
clientId: number;
|
||||
countryCodes: Object;
|
||||
serverVersion?: PiPedalVersion;
|
||||
errorMessage: ObservableProperty<string>;
|
||||
alertMessage: ObservableProperty<string>;
|
||||
@@ -245,6 +248,7 @@ export interface PiPedalModel {
|
||||
jackSettings: ObservableProperty<JackChannelSelection>;
|
||||
banks: ObservableProperty<BankIndex>;
|
||||
jackServerSettings: ObservableProperty<JackServerSettings>;
|
||||
wifiConfigSettings: ObservableProperty<WifiConfigSettings>;
|
||||
|
||||
presets: ObservableProperty<PresetIndex>;
|
||||
|
||||
@@ -320,13 +324,17 @@ export interface PiPedalModel {
|
||||
|
||||
uploadPreset(file: File, uploadAfter: number): Promise<number>;
|
||||
|
||||
setWifiConfigSettings(wifiConfigSettings: WifiConfigSettings): Promise<void>;
|
||||
|
||||
getWifiChannels(countryIso3661: string): Promise<WifiChannel[]>;
|
||||
|
||||
};
|
||||
|
||||
class PiPedalModelImpl implements PiPedalModel {
|
||||
clientId: number = -1;
|
||||
|
||||
serverVersion?: PiPedalVersion;
|
||||
|
||||
countryCodes: Object = {};
|
||||
socketServerUrl: string = "";
|
||||
varServerUrl: string = "";
|
||||
lv2Path: string = "";
|
||||
@@ -346,6 +354,8 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
jackServerSettings: ObservableProperty<JackServerSettings>
|
||||
= new ObservableProperty<JackServerSettings>(new JackServerSettings());
|
||||
|
||||
wifiConfigSettings: ObservableProperty<WifiConfigSettings> = new ObservableProperty<WifiConfigSettings>(new WifiConfigSettings());
|
||||
|
||||
|
||||
presets: ObservableProperty<PresetIndex> = new ObservableProperty<PresetIndex>
|
||||
(
|
||||
@@ -459,6 +469,9 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
} else if (message === "onJackServerSettingsChanged") {
|
||||
let jackServerSettings = new JackServerSettings().deserialize(body);
|
||||
this.jackServerSettings.set(jackServerSettings);
|
||||
} else if (message === "onWifiConfigSettingsChanged") {
|
||||
let wifiConfigSettings = new WifiConfigSettings().deserialize(body);
|
||||
this.wifiConfigSettings.set(wifiConfigSettings);
|
||||
} else if (message === "onBanksChanged") {
|
||||
let banks = new BankIndex().deserialize(body);
|
||||
this.banks.set(banks);
|
||||
@@ -537,6 +550,11 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
.then(data => {
|
||||
this.pedalBoard.set(new PedalBoard().deserialize(data));
|
||||
|
||||
return this.getWebSocket().request<any>("getWifiConfigSettings");
|
||||
})
|
||||
.then(data => {
|
||||
this.wifiConfigSettings.set(new WifiConfigSettings().deserialize(data));
|
||||
|
||||
return this.getWebSocket().request<any>("getJackServerSettings");
|
||||
})
|
||||
.then(data => {
|
||||
@@ -573,7 +591,7 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
})
|
||||
}
|
||||
makeSocketServerUrl(hostName: string, port: number): string {
|
||||
return "ws://" + hostName + ":" + port + "/piddle";
|
||||
return "ws://" + hostName + ":" + port + "/pipedal";
|
||||
|
||||
}
|
||||
makeVarServerUrl(protocol: string, hostName: string, port: number): string {
|
||||
@@ -587,11 +605,12 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
const myRequest = new Request(this.varRequest('config.json'));
|
||||
return fetch(myRequest)
|
||||
.then(
|
||||
response => response.json()
|
||||
|
||||
(response) =>
|
||||
{
|
||||
return response.json();
|
||||
}
|
||||
)
|
||||
.then(data => {
|
||||
console.log("Got config");
|
||||
if (data.max_upload_size)
|
||||
{
|
||||
this.maxUploadSize = data.max_upload_size;
|
||||
@@ -617,6 +636,15 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
return this.webSocket.connect();
|
||||
})
|
||||
.then(() => {
|
||||
const isoRequest = new Request('iso_codes.json');
|
||||
return fetch(isoRequest);
|
||||
})
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((countryCodes) => {
|
||||
this.countryCodes = countryCodes as Object;
|
||||
|
||||
return this.getWebSocket().request<number>("hello");
|
||||
})
|
||||
.then((clientId) => {
|
||||
@@ -652,7 +680,12 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
})
|
||||
.then((data) => {
|
||||
this.presets.set(new PresetIndex().deserialize(data));
|
||||
|
||||
return this.getWebSocket().request<any>("getWifiConfigSettings");
|
||||
})
|
||||
.then(data => {
|
||||
this.wifiConfigSettings.set(new WifiConfigSettings().deserialize(data));
|
||||
|
||||
|
||||
return this.getWebSocket().request<any>("getJackServerSettings");
|
||||
})
|
||||
.then(data => {
|
||||
@@ -1427,6 +1460,75 @@ class PiPedalModelImpl implements PiPedalModel {
|
||||
});
|
||||
return result;
|
||||
}
|
||||
setWifiConfigSettings(wifiConfigSettings: WifiConfigSettings): Promise<void>
|
||||
{
|
||||
let result = new Promise<void>((resolve,reject) =>{
|
||||
let oldSettings = this.wifiConfigSettings.get();
|
||||
wifiConfigSettings = wifiConfigSettings.clone();
|
||||
|
||||
if ((!oldSettings.enable) && (!wifiConfigSettings.enable))
|
||||
{
|
||||
// no effective change.
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
let countryCodeChanged = wifiConfigSettings.countryCode !== oldSettings.countryCode;
|
||||
if (!wifiConfigSettings.enable)
|
||||
{
|
||||
wifiConfigSettings.hasPassword = false;
|
||||
wifiConfigSettings.hotspotName = oldSettings.hotspotName;
|
||||
} else {
|
||||
if (!wifiConfigSettings.hasPassword) {
|
||||
if (wifiConfigSettings.hotspotName === oldSettings.hotspotName && !countryCodeChanged) {
|
||||
// no effective change.
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// save a version for the server (potentially carrying a password)
|
||||
let serverConfigSettings = wifiConfigSettings.clone();
|
||||
|
||||
|
||||
|
||||
// notify the server.
|
||||
let ws = this.webSocket;
|
||||
if (!ws)
|
||||
{
|
||||
reject("Not connected.");
|
||||
return;
|
||||
}
|
||||
ws.request<void>(
|
||||
"setWifiConfigSettings",
|
||||
serverConfigSettings
|
||||
)
|
||||
.then(()=> {
|
||||
resolve();
|
||||
})
|
||||
.catch((err) =>{
|
||||
reject(err);
|
||||
});
|
||||
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
getWifiChannels(countryIso3661: string): Promise<WifiChannel[]>
|
||||
{
|
||||
let result = new Promise<WifiChannel[]>((resolve,reject) => {
|
||||
if (!this.webSocket) {
|
||||
reject("Connection closed.");
|
||||
return;
|
||||
}
|
||||
this.webSocket.request<WifiChannel[]>("getWifiChannels",countryIso3661)
|
||||
.then((data) => {
|
||||
resolve(WifiChannel.deserialize_array(data));
|
||||
})
|
||||
.catch((err)=> reject(err));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -100,12 +100,12 @@ const styles = (theme: Theme) => createStyles({
|
||||
marginRight: 8,
|
||||
marginBottom: 12,
|
||||
position: "relative",
|
||||
paddingLeft: 0,
|
||||
paddingLeft: 3,
|
||||
paddingRight: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
border: "2pt #AAA solid",
|
||||
borderRadius: 10,
|
||||
borderRadius: 4,
|
||||
elevation: 12,
|
||||
display: "flex",
|
||||
flexDirection: "row", flexWrap: "wrap",
|
||||
|
||||
@@ -95,7 +95,7 @@ export default class RenameDialog extends ResizeResponsiveComponent<RenameDialog
|
||||
}
|
||||
componentWillUnmount()
|
||||
{
|
||||
super.componentDidMount();
|
||||
super.componentWillUnmount();
|
||||
this.mounted = false;
|
||||
this.updateHooks();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
import ButtonBase from "@material-ui/core/ButtonBase";
|
||||
import { TransitionProps } from '@material-ui/core/transitions/transition';
|
||||
import Slide from '@material-ui/core/Slide';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/styles';
|
||||
@@ -18,6 +17,9 @@ import SelectHoverBackground from './SelectHoverBackground';
|
||||
import JackServerSettings from './JackServerSettings';
|
||||
import JackServerSettingsDialog from './JackServerSettingsDialog';
|
||||
import JackHostStatus from './JackHostStatus';
|
||||
import WifiConfigSettings from './WifiConfigSettings';
|
||||
import WifiConfigDialog from './WifiConfigDialog';
|
||||
import DialogEx from './DialogEx'
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +36,9 @@ interface SettingsDialogState {
|
||||
jackServerSettings: JackServerSettings;
|
||||
jackStatus?: JackHostStatus;
|
||||
|
||||
wifiConfigSettings: WifiConfigSettings;
|
||||
|
||||
showWifiConfigDialog: boolean;
|
||||
showInputSelectDialog: boolean;
|
||||
showOutputSelectDialog: boolean;
|
||||
showMidiSelectDialog: boolean;
|
||||
@@ -120,6 +125,8 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
jackConfiguration: this.model.jackConfiguration.get(),
|
||||
jackStatus: undefined,
|
||||
jackSettings: this.model.jackSettings.get(),
|
||||
wifiConfigSettings: this.model.wifiConfigSettings.get(),
|
||||
showWifiConfigDialog: false,
|
||||
showInputSelectDialog: false,
|
||||
showOutputSelectDialog: false,
|
||||
showMidiSelectDialog: false,
|
||||
@@ -132,10 +139,28 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
this.handleJackConfigurationChanged = this.handleJackConfigurationChanged.bind(this);
|
||||
this.handleJackSettingsChanged = this.handleJackSettingsChanged.bind(this);
|
||||
this.handleJackServerSettingsChanged = this.handleJackServerSettingsChanged.bind(this);
|
||||
this.handleWifiConfigSettingsChanged = this.handleWifiConfigSettingsChanged.bind(this);
|
||||
|
||||
}
|
||||
|
||||
handleApplyWifiConfig(wifiConfigSettings: WifiConfigSettings): void {
|
||||
this.setState({showWifiConfigDialog: false});
|
||||
this.model.setWifiConfigSettings(wifiConfigSettings)
|
||||
.then(() => {
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
this.model.showAlert(err);
|
||||
});
|
||||
}
|
||||
|
||||
handleWifiConfigSettingsChanged(): void {
|
||||
this.setState(
|
||||
{
|
||||
wifiConfigSettings: this.model.wifiConfigSettings.get()
|
||||
}
|
||||
)
|
||||
}
|
||||
handleJackSettingsChanged(): void {
|
||||
this.setState({
|
||||
jackSettings: this.model.jackSettings.get()
|
||||
@@ -177,6 +202,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
this.model.jackSettings.addOnChangedHandler(this.handleJackSettingsChanged);
|
||||
this.model.jackConfiguration.addOnChangedHandler(this.handleJackConfigurationChanged);
|
||||
this.model.jackServerSettings.addOnChangedHandler(this.handleJackServerSettingsChanged);
|
||||
this.model.wifiConfigSettings.addOnChangedHandler(this.handleWifiConfigSettingsChanged);
|
||||
this.model.getJackStatus()
|
||||
.then((jackStatus) =>
|
||||
this.setState(
|
||||
@@ -193,7 +219,8 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
this.handleJackConfigurationChanged();
|
||||
this.handleJackSettingsChanged();
|
||||
this.handleJackServerSettingsChanged();
|
||||
this.timerHandle = setInterval(() => this.tick(), 1000);
|
||||
this.handleWifiConfigSettingsChanged();
|
||||
// xxx UNCOMMENT ME! this.timerHandle = setInterval(() => this.tick(), 1000);
|
||||
} else {
|
||||
if (this.timerHandle) {
|
||||
clearInterval(this.timerHandle);
|
||||
@@ -201,6 +228,8 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
this.model.jackConfiguration.removeOnChangedHandler(this.handleJackConfigurationChanged);
|
||||
this.model.jackSettings.removeOnChangedHandler(this.handleJackSettingsChanged);
|
||||
this.model.jackServerSettings.removeOnChangedHandler(this.handleJackServerSettingsChanged);
|
||||
this.model.wifiConfigSettings.removeOnChangedHandler(this.handleWifiConfigSettingsChanged);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,25 +321,33 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
if (ports.length === 1) return ports[0];
|
||||
return ports.length + " channels";
|
||||
}
|
||||
|
||||
handleShowWifiConfigDialog() {
|
||||
this.setState({
|
||||
showWifiConfigDialog: true
|
||||
});
|
||||
}
|
||||
handleRestart() {
|
||||
this.setState({ restarting: true });
|
||||
this.model.restart()
|
||||
.then(() => {
|
||||
this.setState({ restarting: true });
|
||||
// this.setState({ restarting: true });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.model.showAlert(error);
|
||||
this.setState({ restarting: false });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
handleShutdown() {
|
||||
this.setState({ shuttingDown: true });
|
||||
this.model.shutdown()
|
||||
.then(() => {
|
||||
this.setState({ shuttingDown: true });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.model.showAlert(error);
|
||||
this.setState({ shuttingDown: false });
|
||||
});
|
||||
|
||||
}
|
||||
@@ -322,7 +359,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
let disableShutdown = this.state.shuttingDown || this.state.restarting;
|
||||
|
||||
return (
|
||||
<Dialog fullScreen open={this.props.open}
|
||||
<DialogEx tag="SettingsDialog" fullScreen open={this.props.open}
|
||||
onClose={() => { this.props.onClose() }} TransitionComponent={Transition}>
|
||||
|
||||
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
|
||||
@@ -428,6 +465,18 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
<Divider />
|
||||
<div >
|
||||
<Typography className={classes.sectionHead} display="block" variant="caption" color="secondary">SYSTEM</Typography>
|
||||
<ButtonBase className={classes.setting} disabled={!this.state.wifiConfigSettings.valid}
|
||||
onClick={() => this.handleShowWifiConfigDialog()} >
|
||||
<SelectHoverBackground selected={false} showHover={true} />
|
||||
<div style={{ width: "100%" }}>
|
||||
<Typography className={classes.primaryItem} display="block" variant="body2" color="textPrimary" noWrap>
|
||||
Configure Wi-fi Hotspot</Typography>
|
||||
<Typography display="block" variant="caption" noWrap color="textSecondary">
|
||||
{this.state.wifiConfigSettings.getSummaryText()}
|
||||
</Typography>
|
||||
|
||||
</div>
|
||||
</ButtonBase>
|
||||
<ButtonBase className={classes.setting} disabled={!isConfigValid || disableShutdown}
|
||||
onClick={() => this.handleRestart()} >
|
||||
<SelectHoverBackground selected={false} showHover={true} />
|
||||
@@ -452,7 +501,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
) : (
|
||||
<Typography className={classes.primaryItem} display="block" variant="body2" noWrap>Shut down</Typography>
|
||||
)
|
||||
}
|
||||
}
|
||||
</div >
|
||||
</ButtonBase>
|
||||
</div>
|
||||
@@ -483,8 +532,12 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
|
||||
)
|
||||
}
|
||||
<WifiConfigDialog wifiConfigSettings={this.state.wifiConfigSettings} open={this.state.showWifiConfigDialog}
|
||||
onClose={()=> this.setState({showWifiConfigDialog: false})}
|
||||
onOk={(wifiConfigSettings) => this.handleApplyWifiConfig(wifiConfigSettings)}
|
||||
/>
|
||||
|
||||
</Dialog >
|
||||
</DialogEx >
|
||||
|
||||
);
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ export default class UploadDialog extends ResizeResponsiveComponent<UploadDialog
|
||||
this.updateHooks();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
super.componentDidMount();
|
||||
super.componentWillUnmount();
|
||||
this.mounted = false;
|
||||
this.updateHooks();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
export default class WifiChannel {
|
||||
deserialize(input: any): WifiChannel {
|
||||
this.channelId = input.channelId;
|
||||
this.channelName = input.channelName;
|
||||
return this;
|
||||
}
|
||||
static deserialize_array(input: any): WifiChannel[]
|
||||
{
|
||||
let result: WifiChannel[] = [];
|
||||
for (let i = 0; i < input.length; ++i)
|
||||
{
|
||||
result.push(new WifiChannel().deserialize(input[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
channelId: string = "";
|
||||
channelName: string = "";
|
||||
};
|
||||
@@ -0,0 +1,374 @@
|
||||
import React from 'react';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import Switch from '@material-ui/core/Switch';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||
import WifiConfigSettings from './WifiConfigSettings';
|
||||
import NoChangePassword from './NoChangePassword';
|
||||
import DialogEx from './DialogEx'
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { Theme, withStyles, WithStyles,createStyles } from '@material-ui/core/styles';
|
||||
import Select from '@material-ui/core/Select';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import InputLabel from '@material-ui/core/InputLabel';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import WifiChannel from './WifiChannel';
|
||||
import {PiPedalModel, PiPedalModelFactory} from './PiPedalModel';
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
pgraph: {
|
||||
paddingBottom: 16
|
||||
}
|
||||
});
|
||||
|
||||
const NBSP = "\u00A0";
|
||||
|
||||
export interface WifiConfigProps extends WithStyles<typeof styles> {
|
||||
open: boolean,
|
||||
wifiConfigSettings: WifiConfigSettings,
|
||||
onOk: (wifiConfigSettings: WifiConfigSettings) => void,
|
||||
onClose: () => void
|
||||
};
|
||||
|
||||
export interface WifiConfigState {
|
||||
fullScreen: boolean;
|
||||
showWifiWarningDialog: boolean;
|
||||
wifiWarningGiven: boolean;
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
newPassword: string;
|
||||
nameError: boolean;
|
||||
nameErrorMessage: string;
|
||||
passwordError: boolean;
|
||||
passwordErrorMessage: string;
|
||||
countryCode: string;
|
||||
channel: string;
|
||||
wifiChannels: WifiChannel[];
|
||||
};
|
||||
|
||||
|
||||
let validNameRegex = /^[a-zA-Z][a-zA-Z0-9_-]*$/
|
||||
function isValidName(text: string)
|
||||
{
|
||||
return validNameRegex.test(text);
|
||||
}
|
||||
|
||||
const WifiConfigDialog = withStyles(styles, { withTheme: true })(
|
||||
class extends ResizeResponsiveComponent<WifiConfigProps, WifiConfigState> {
|
||||
|
||||
refName: React.RefObject<HTMLInputElement>;
|
||||
refPassword: React.RefObject<HTMLInputElement>;
|
||||
model: PiPedalModel;
|
||||
|
||||
constructor(props: WifiConfigProps) {
|
||||
super(props);
|
||||
this.model = PiPedalModelFactory.getInstance();
|
||||
this.state = {
|
||||
fullScreen: false,
|
||||
enabled: this.props.wifiConfigSettings.enable,
|
||||
name: this.props.wifiConfigSettings.hotspotName,
|
||||
newPassword: "",
|
||||
nameError: false,
|
||||
nameErrorMessage: NBSP,
|
||||
passwordError: false,
|
||||
showWifiWarningDialog: false,
|
||||
wifiWarningGiven: this.props.wifiConfigSettings.wifiWarningGiven,
|
||||
passwordErrorMessage: NBSP,
|
||||
countryCode: this.props.wifiConfigSettings.countryCode,
|
||||
channel: this.props.wifiConfigSettings.channel,
|
||||
wifiChannels: []
|
||||
};
|
||||
this.model.getWifiChannels(this.props.wifiConfigSettings.countryCode)
|
||||
.then((wifiChannels_) => {
|
||||
this.setState({wifiChannels: wifiChannels_});
|
||||
}).catch((err)=> {});
|
||||
|
||||
this.refName = React.createRef<HTMLInputElement>();
|
||||
this.refPassword = React.createRef<HTMLInputElement>();
|
||||
this.handlePopState = this.handlePopState.bind(this);
|
||||
}
|
||||
mounted: boolean = false;
|
||||
|
||||
hasHooks: boolean = false;
|
||||
|
||||
stateWasPopped: boolean = false;
|
||||
|
||||
handleEnableChanged(e: any) {
|
||||
this.setState({ enabled: e.target.checked });
|
||||
}
|
||||
handlePopState(e: any): any {
|
||||
this.stateWasPopped = true;
|
||||
let shouldClose = (!e.state || !e.state.WifiConfig);
|
||||
if (shouldClose) {
|
||||
this.props.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateHooks(): void {
|
||||
let wantHooks = this.mounted && this.props.open;
|
||||
if (wantHooks !== this.hasHooks) {
|
||||
this.hasHooks = wantHooks;
|
||||
|
||||
if (this.hasHooks) {
|
||||
this.stateWasPopped = false;
|
||||
window.addEventListener("popstate", this.handlePopState);
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
let state = history.state;
|
||||
if (!state) {
|
||||
state = {};
|
||||
}
|
||||
state.WifiConfig = true;
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
history.pushState(
|
||||
state,
|
||||
"Wi-Fi Configuration",
|
||||
"#WifiConfig"
|
||||
);
|
||||
} else {
|
||||
window.removeEventListener("popstate", this.handlePopState);
|
||||
if (!this.stateWasPopped) {
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
onWindowSizeChanged(width: number, height: number): void {
|
||||
this.setState({ fullScreen: height < 200 })
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
this.mounted = true;
|
||||
this.updateHooks();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
this.mounted = false;
|
||||
this.updateHooks();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: WifiConfigProps) {
|
||||
this.updateHooks();
|
||||
|
||||
if (this.props.open && !prevProps.open)
|
||||
{
|
||||
this.setState({
|
||||
enabled: this.props.wifiConfigSettings.enable,
|
||||
name: this.props.wifiConfigSettings.hotspotName,
|
||||
newPassword: "",
|
||||
wifiWarningGiven: this.props.wifiConfigSettings.wifiWarningGiven,
|
||||
countryCode: this.props.wifiConfigSettings.countryCode,
|
||||
channel: this.props.wifiConfigSettings.channel
|
||||
});
|
||||
|
||||
if (this.props.wifiConfigSettings.countryCode !== this.state.countryCode)
|
||||
{
|
||||
this.model.getWifiChannels(this.props.wifiConfigSettings.countryCode)
|
||||
.then((wifiChannels) => {
|
||||
this.setState({wifiChannels: wifiChannels});
|
||||
})
|
||||
.catch((error) => {});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleOk(wifiWarningGiven: boolean) {
|
||||
let hasError = false;
|
||||
if (this.state.enabled)
|
||||
{
|
||||
let name = this.state.name;
|
||||
if (name.length === 0) {
|
||||
this.setState({nameError: true, nameErrorMessage: "* Required"});
|
||||
hasError = true;
|
||||
} else {
|
||||
if (!isValidName(name))
|
||||
{
|
||||
this.setState({nameError: true, nameErrorMessage: "Invalid name"});
|
||||
hasError = true;
|
||||
} else if (name.length > 15)
|
||||
{
|
||||
this.setState({nameError: true, nameErrorMessage: "> 15 characters"});
|
||||
hasError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.state.enabled && (!this.props.wifiConfigSettings.hasPassword) && this.state.newPassword.length === 0)
|
||||
{
|
||||
this.setState({passwordError: true, passwordErrorMessage: "* Required"});
|
||||
hasError = true;
|
||||
}
|
||||
if (!hasError)
|
||||
{
|
||||
let wifiConfigSettings = new WifiConfigSettings();
|
||||
wifiConfigSettings.valid = true;
|
||||
|
||||
wifiConfigSettings.enable = this.state.enabled;
|
||||
wifiConfigSettings.hotspotName = this.state.name;
|
||||
if (this.state.newPassword.length === 0 || !this.state.enabled)
|
||||
{
|
||||
wifiConfigSettings.hasPassword = false;
|
||||
} else {
|
||||
wifiConfigSettings.hasPassword = true;
|
||||
wifiConfigSettings.password = this.state.newPassword;
|
||||
}
|
||||
|
||||
if (!this.props.wifiConfigSettings.wifiWarningGiven && !wifiWarningGiven) {
|
||||
this.setState({showWifiWarningDialog: true});
|
||||
} else {
|
||||
wifiConfigSettings.wifiWarningGiven = true;
|
||||
this.props.onOk(wifiConfigSettings);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
handleChannelChange(e: any)
|
||||
{
|
||||
let value = e.target.value as string;
|
||||
this.setState({channel: value });
|
||||
}
|
||||
handleCountryChanged(e: any)
|
||||
{
|
||||
let value = e.target.value as string;
|
||||
|
||||
this.setState({countryCode: value});
|
||||
this.model.getWifiChannels(value)
|
||||
.then(wifiChannels => {
|
||||
this.setState({wifiChannels: wifiChannels});
|
||||
})
|
||||
.catch((error)=> { });
|
||||
}
|
||||
|
||||
render() {
|
||||
let props = this.props;
|
||||
let classes = this.props.classes;
|
||||
let { open, onClose} = props;
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} fullWidth onClose={handleClose} style={{}}
|
||||
fullScreen={this.state.fullScreen}
|
||||
>
|
||||
{ this.state.fullScreen && (
|
||||
<DialogTitle>Wi-fi Hotspot</DialogTitle>
|
||||
)}
|
||||
<DialogContent>
|
||||
|
||||
<FormControlLabel
|
||||
control={(
|
||||
<Switch
|
||||
checked={this.state.enabled}
|
||||
onChange={(e: any) => this.handleEnableChanged(e)}
|
||||
color="secondary"
|
||||
/>
|
||||
)}
|
||||
label="Enable"
|
||||
/>
|
||||
<TextField style={{ marginBottom: 16, marginTop: 16 }}
|
||||
|
||||
autoComplete="off"
|
||||
id="name"
|
||||
spellCheck="false"
|
||||
label="SSID"
|
||||
type="text"
|
||||
fullWidth
|
||||
error={this.state.nameError}
|
||||
helperText={this.state.nameErrorMessage}
|
||||
value={this.state.name}
|
||||
onChange={(e) => this.setState({name: e.target.value, nameError: false, nameErrorMessage: NBSP})}
|
||||
inputRef={this.refName}
|
||||
disabled={!this.state.enabled}
|
||||
/>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<NoChangePassword
|
||||
onPasswordChange={(text): void => { this.setState({ newPassword: text, passwordError: false, passwordErrorMessage: NBSP }); }}
|
||||
hasPassword={this.props.wifiConfigSettings.hasPassword}
|
||||
label="WEP Passphrase"
|
||||
error={this.state.passwordError}
|
||||
helperText={this.state.passwordErrorMessage}
|
||||
defaultValue={this.state.newPassword}
|
||||
disabled={!this.state.enabled}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 16}}>
|
||||
<FormControl>
|
||||
<InputLabel htmlFor="countryCodeSelect">Country</InputLabel>
|
||||
<Select id="countryCodeSelect" value={this.state.countryCode} style={{width: 220}}
|
||||
onChange={(event)=>this.handleCountryChanged(event)} >
|
||||
{Object.entries(this.model.countryCodes).map(([key,value])=> {
|
||||
return (
|
||||
<MenuItem value={key}>{value}</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
</div>
|
||||
<div style={{ marginBottom: 24}}>
|
||||
<FormControl>
|
||||
<InputLabel htmlFor="channelSelect">Channel</InputLabel>
|
||||
<Select id="channelSelect" value={this.state.channel} style={{width: 220}} onChange={(e)=>{
|
||||
this.handleChannelChange(e);
|
||||
}}>
|
||||
{this.state.wifiChannels.map((channel)=> {
|
||||
return (
|
||||
<MenuItem value={channel.channelId}>{channel.channelName}</MenuItem>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
</div>
|
||||
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleClose} color="primary" style={{ width: 120 }}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={()=> this.handleOk(false)} color="secondary" style={{ width: 120 }} >
|
||||
OK
|
||||
</Button>
|
||||
</DialogActions>
|
||||
<DialogEx open={this.state.showWifiWarningDialog} tag="wifiConfirm" >
|
||||
<DialogContent>
|
||||
<Typography className={classes.pgraph} variant="body2" color="textPrimary">
|
||||
Enabling the Wi-Fi hotspot will disable regular Wi-Fi network access on the PiPedal device. Once
|
||||
enabled, connect to the hotspot and launch http://172.24.1.1 or http://{this.state.name}.local to access the PiPedal web app again.
|
||||
</Typography>
|
||||
<Typography className={classes.pgraph} variant="body2" color="textPrimary" gutterBottom>
|
||||
Are you sure you want to proceed?
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={()=> this.setState({showWifiWarningDialog: false})} color="primary" style={{ width: 120 }}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={()=> {
|
||||
this.setState({showWifiWarningDialog: false});
|
||||
this.handleOk(true);
|
||||
}} color="secondary" style={{ width: 120 }} >
|
||||
PROCEED
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</DialogEx>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default WifiConfigDialog;
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
|
||||
export default class WifiConfigSettings {
|
||||
deserialize(input: any) : WifiConfigSettings{
|
||||
this.valid = input.valid;
|
||||
this.wifiWarningGiven = input.wifiWarningGiven;
|
||||
this.rebootRequired = input.rebootRequired;
|
||||
this.enable = input.enable;
|
||||
this.hotspotName = input.hotspotName;
|
||||
this.hasPassword = input.hasPassword;
|
||||
this.password = input.password;
|
||||
this.countryCode = input.countryCode;
|
||||
this.channel = input.channel;
|
||||
return this;
|
||||
}
|
||||
clone() : WifiConfigSettings {
|
||||
return this.deserialize(this);
|
||||
}
|
||||
valid: boolean = true;
|
||||
wifiWarningGiven: boolean = false;
|
||||
enable: boolean = true;
|
||||
hasPassword: boolean = false;
|
||||
rebootRequired = false;
|
||||
hotspotName: string = "pipedal";
|
||||
password: string = "";
|
||||
countryCode: string = "US";
|
||||
channel: string = "g6";
|
||||
|
||||
getSummaryText() {
|
||||
let result: string;
|
||||
if (!this.valid) {
|
||||
result = "Not available.";
|
||||
} else if (!this.enable) {
|
||||
result = "Disabled.";
|
||||
} else {
|
||||
result = this.hotspotName;
|
||||
}
|
||||
if (this.rebootRequired)
|
||||
{
|
||||
result += " (Restart required)";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Theme, withStyles, WithStyles,createStyles } from '@material-ui/core/styles';
|
||||
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
});
|
||||
|
||||
|
||||
interface XxxProps extends WithStyles<typeof styles> {
|
||||
theme: Theme,
|
||||
};
|
||||
|
||||
interface XxxState {
|
||||
|
||||
};
|
||||
|
||||
const Xxx = withStyles(styles, { withTheme: true })(
|
||||
|
||||
class extends React.Component<XxxProps, XxxState> {
|
||||
constructor(props: XxxProps)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div/>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default Xxx;
|
||||
Reference in New Issue
Block a user