Merge pull request #230 from hyperspacedev/feat/check-bypass
Added instance name validation bypass
This commit is contained in:
commit
07be3af687
|
@ -20,7 +20,7 @@ import {
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogContentText,
|
DialogContentText,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
TextField,
|
TextField
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import { withSnackbar } from "notistack";
|
import { withSnackbar } from "notistack";
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
viewIsLoading: true,
|
viewIsLoading: true,
|
||||||
viewDidLoad: false,
|
viewDidLoad: false,
|
||||||
viewDidError: false,
|
viewDidError: false,
|
||||||
blockTextField: "",
|
blockTextField: ""
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +64,14 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
this.setState({
|
this.setState({
|
||||||
blockedServers: resp.data,
|
blockedServers: resp.data,
|
||||||
viewDidLoad: true,
|
viewDidLoad: true,
|
||||||
viewIsLoading: false,
|
viewIsLoading: false
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
this.setState({
|
this.setState({
|
||||||
viewIsLoading: false,
|
viewIsLoading: false,
|
||||||
viewDidError: true,
|
viewDidError: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
this.setState({
|
this.setState({
|
||||||
blockTextField: "",
|
blockTextField: "",
|
||||||
addBlockOpen: false,
|
addBlockOpen: false,
|
||||||
blockedServers,
|
blockedServers
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
blockedServers.splice(blockedServers.indexOf(domain), 1);
|
blockedServers.splice(blockedServers.indexOf(domain), 1);
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
blockedServers,
|
blockedServers
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
|
@ -118,7 +118,7 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
|
|
||||||
updateTextField(value: string) {
|
updateTextField(value: string) {
|
||||||
this.setState({
|
this.setState({
|
||||||
blockTextField: value,
|
blockTextField: value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
fullWidth
|
fullWidth
|
||||||
value={this.state.blockTextField}
|
value={this.state.blockTextField}
|
||||||
placeholder="mastodon.online"
|
placeholder="mastodon.online"
|
||||||
onChange={(e) => this.updateTextField(e.target.value)}
|
onChange={e => this.updateTextField(e.target.value)}
|
||||||
></TextField>
|
></TextField>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
@ -153,9 +153,7 @@ class Blocked extends Component<any, IBlockedState> {
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={(e) =>
|
onClick={e => this.addBlock(this.state.blockTextField)}
|
||||||
this.addBlock(this.state.blockTextField)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
ListItemSecondaryAction,
|
ListItemSecondaryAction,
|
||||||
IconButton,
|
IconButton,
|
||||||
InputAdornment,
|
InputAdornment
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import { styles } from "./WelcomePage.styles";
|
import { styles } from "./WelcomePage.styles";
|
||||||
import Mastodon from "megalodon";
|
import Mastodon from "megalodon";
|
||||||
|
@ -28,7 +28,7 @@ import {
|
||||||
createHyperspaceApp,
|
createHyperspaceApp,
|
||||||
getRedirectAddress,
|
getRedirectAddress,
|
||||||
inDisallowedDomains,
|
inDisallowedDomains,
|
||||||
instancesBearerKey,
|
instancesBearerKey
|
||||||
} from "../utilities/login";
|
} from "../utilities/login";
|
||||||
import { parseUrl } from "query-string";
|
import { parseUrl } from "query-string";
|
||||||
import { getConfig } from "../utilities/settings";
|
import { getConfig } from "../utilities/settings";
|
||||||
|
@ -39,7 +39,7 @@ import { Config } from "../types/Config";
|
||||||
import {
|
import {
|
||||||
getAccountRegistry,
|
getAccountRegistry,
|
||||||
loginWithAccount,
|
loginWithAccount,
|
||||||
removeAccountFromRegistry,
|
removeAccountFromRegistry
|
||||||
} from "../utilities/accounts";
|
} from "../utilities/accounts";
|
||||||
import { MultiAccount } from "../types/Account";
|
import { MultiAccount } from "../types/Account";
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
authCode: "",
|
authCode: "",
|
||||||
emergencyMode: false,
|
emergencyMode: false,
|
||||||
version: "",
|
version: "",
|
||||||
willAddAccount: false,
|
willAddAccount: false
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read the configuration data and update the state
|
// Read the configuration data and update the state
|
||||||
|
@ -253,7 +253,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
? config.location
|
? config.location
|
||||||
: `https://${window.location.host}`,
|
: `https://${window.location.host}`,
|
||||||
redirectAddressIsDynamic: config.location === "dynamic",
|
redirectAddressIsDynamic: config.location === "dynamic",
|
||||||
version: config.version,
|
version: config.version
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -274,7 +274,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
if (localStorage.getItem("login")) {
|
if (localStorage.getItem("login")) {
|
||||||
this.getSavedSession();
|
this.getSavedSession();
|
||||||
this.setState({
|
this.setState({
|
||||||
foundSavedLogin: true,
|
foundSavedLogin: true
|
||||||
});
|
});
|
||||||
this.checkForToken();
|
this.checkForToken();
|
||||||
}
|
}
|
||||||
|
@ -334,7 +334,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
clientId: session.clientId,
|
clientId: session.clientId,
|
||||||
clientSecret: session.clientSecret,
|
clientSecret: session.clientSecret,
|
||||||
authUrl: session.authUrl,
|
authUrl: session.authUrl,
|
||||||
emergencyMode: session.emergency,
|
emergencyMode: session.emergency
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,8 +392,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
this.setState({ user: newUser });
|
this.setState({ user: newUser });
|
||||||
return "https://" + newUser.split("@")[1];
|
return "https://" + newUser.split("@")[1];
|
||||||
} else {
|
} else {
|
||||||
let newUser = `${user}@${this.state.registerBase ?? "mastodon.online"
|
let newUser = `${user}@${this.state.registerBase ??
|
||||||
}`;
|
"mastodon.online"}`;
|
||||||
this.setState({ user: newUser });
|
this.setState({ user: newUser });
|
||||||
return (
|
return (
|
||||||
"https://" + (this.state.registerBase ?? "mastodon.online")
|
"https://" + (this.state.registerBase ?? "mastodon.online")
|
||||||
|
@ -403,8 +403,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
|
|
||||||
// Otherwise, treat them as if they're from the server
|
// Otherwise, treat them as if they're from the server
|
||||||
else {
|
else {
|
||||||
let newUser = `${user}@${this.state.registerBase ?? "mastodon.online"
|
let newUser = `${user}@${this.state.registerBase ??
|
||||||
}`;
|
"mastodon.online"}`;
|
||||||
this.setState({ user: newUser });
|
this.setState({ user: newUser });
|
||||||
return "https://" + (this.state.registerBase ?? "mastodon.online");
|
return "https://" + (this.state.registerBase ?? "mastodon.online");
|
||||||
}
|
}
|
||||||
|
@ -413,10 +413,11 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
/**
|
/**
|
||||||
* Check the user string for any errors and then create a client with an
|
* Check the user string for any errors and then create a client with an
|
||||||
* ID and secret to start the authorization process.
|
* ID and secret to start the authorization process.
|
||||||
|
* @param bypassChecks Whether to bypass the checks in place.
|
||||||
*/
|
*/
|
||||||
startLogin() {
|
startLogin(bypassChecks: boolean = false) {
|
||||||
// Check if we have errored
|
// Check if we have errored
|
||||||
let error = this.checkForErrors(this.state.user);
|
let error = this.checkForErrors(this.state.user, bypassChecks);
|
||||||
|
|
||||||
// If we didn't, create the Hyperspace app to register onto that Mastodon
|
// If we didn't, create the Hyperspace app to register onto that Mastodon
|
||||||
// server.
|
// server.
|
||||||
|
@ -439,7 +440,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
clientId: resp.clientId,
|
clientId: resp.clientId,
|
||||||
clientSecret: resp.clientSecret,
|
clientSecret: resp.clientSecret,
|
||||||
authUrl: resp.url,
|
authUrl: resp.url,
|
||||||
emergency: false,
|
emergency: false
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"login",
|
"login",
|
||||||
|
@ -451,8 +452,17 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
clientId: resp.clientId,
|
clientId: resp.clientId,
|
||||||
clientSecret: resp.clientSecret,
|
clientSecret: resp.clientSecret,
|
||||||
authUrl: resp.url,
|
authUrl: resp.url,
|
||||||
proceedToGetCode: true,
|
proceedToGetCode: true
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch((err: Error) => {
|
||||||
|
this.props.enqueueSnackbar(
|
||||||
|
`Failed to register app at ${baseurl.replace(
|
||||||
|
"https://",
|
||||||
|
""
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
console.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,7 +485,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
Mastodon.registerApp(
|
Mastodon.registerApp(
|
||||||
this.state.brandName ?? "Hyperspace",
|
this.state.brandName ?? "Hyperspace",
|
||||||
{
|
{
|
||||||
scopes: scopes,
|
scopes: scopes
|
||||||
},
|
},
|
||||||
baseurl
|
baseurl
|
||||||
)
|
)
|
||||||
|
@ -485,7 +495,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
clientId: appData.clientId,
|
clientId: appData.clientId,
|
||||||
clientSecret: appData.clientSecret,
|
clientSecret: appData.clientSecret,
|
||||||
authUrl: appData.url,
|
authUrl: appData.url,
|
||||||
emergency: true,
|
emergency: true
|
||||||
};
|
};
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"login",
|
"login",
|
||||||
|
@ -496,7 +506,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
this.setState({
|
this.setState({
|
||||||
clientId: appData.clientId,
|
clientId: appData.clientId,
|
||||||
clientSecret: appData.clientSecret,
|
clientSecret: appData.clientSecret,
|
||||||
authUrl: appData.url,
|
authUrl: appData.url
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -528,15 +538,21 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
clientSecret: session.clientSecret,
|
clientSecret: session.clientSecret,
|
||||||
authUrl: session.authUrl,
|
authUrl: session.authUrl,
|
||||||
emergencyMode: session.emergency,
|
emergencyMode: session.emergency,
|
||||||
proceedToGetCode: true,
|
proceedToGetCode: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the user input string for any possible errors
|
* Check the user input string for any possible errors
|
||||||
|
* @param username The username to read and check for errors
|
||||||
|
* @param bypassesInstanceNameCheck Whether to bypass the instance name validation process. Defaults to false.
|
||||||
|
* @return Whether an error has occured in the validation.
|
||||||
*/
|
*/
|
||||||
checkForErrors(username: string): boolean {
|
checkForErrors(
|
||||||
|
username: string,
|
||||||
|
bypassesInstanceNameCheck: boolean = false
|
||||||
|
): boolean {
|
||||||
let userInputError = false;
|
let userInputError = false;
|
||||||
let userInputErrorMessage = "";
|
let userInputErrorMessage = "";
|
||||||
|
|
||||||
|
@ -555,28 +571,31 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
if (inDisallowedDomains(baseUrl)) {
|
if (inDisallowedDomains(baseUrl)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
userInputError: true,
|
userInputError: true,
|
||||||
userInputErrorMessage: `Signing in with an account from ${baseUrl} isn't supported.`,
|
userInputErrorMessage: `Signing in with an account from ${baseUrl} isn't supported.`
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
if (bypassesInstanceNameCheck) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Are we unable to ping the server?
|
// Are we unable to ping the server?
|
||||||
axios
|
axios
|
||||||
.get(
|
.get(
|
||||||
"https://instances.social/api/1.0/instances/show?name=" +
|
"https://instances.social/api/1.0/instances/show?name=" +
|
||||||
baseUrl,
|
baseUrl,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${instancesBearerKey}`,
|
Authorization: `Bearer ${instancesBearerKey}`
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
let userInputError = true;
|
let userInputError = true;
|
||||||
let userInputErrorMessage =
|
let userInputErrorMessage =
|
||||||
"Instance name is invalid.";
|
"We couldn't recognize this instance.";
|
||||||
this.setState({
|
this.setState({
|
||||||
userInputError,
|
userInputError,
|
||||||
userInputErrorMessage,
|
userInputErrorMessage
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -633,9 +652,9 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
|
|
||||||
let redirectUrl: string | undefined =
|
let redirectUrl: string | undefined =
|
||||||
this.state.emergencyMode ||
|
this.state.emergencyMode ||
|
||||||
clientLoginSession.authUrl.includes(
|
clientLoginSession.authUrl.includes(
|
||||||
"urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob"
|
"urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob"
|
||||||
)
|
)
|
||||||
? undefined
|
? undefined
|
||||||
: getRedirectAddress(conf.location);
|
: getRedirectAddress(conf.location);
|
||||||
|
|
||||||
|
@ -658,8 +677,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
this.props.enqueueSnackbar(
|
this.props.enqueueSnackbar(
|
||||||
`Couldn't authorize ${this.state.brandName ?? "Hyperspace"
|
`Couldn't authorize ${this.state.brandName ??
|
||||||
}: ${err.name}`,
|
"Hyperspace"}: ${err.name}`,
|
||||||
{ variant: "error" }
|
{ variant: "error" }
|
||||||
);
|
);
|
||||||
console.error(err.message);
|
console.error(err.message);
|
||||||
|
@ -677,8 +696,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
window.location.protocol === "hyperspace:"
|
window.location.protocol === "hyperspace:"
|
||||||
? "hyperspace://hyperspace/app/"
|
? "hyperspace://hyperspace/app/"
|
||||||
: this.state.redirectAddressIsDynamic
|
: this.state.redirectAddressIsDynamic
|
||||||
? `https://${window.location.host}/#/`
|
? `https://${window.location.host}/#/`
|
||||||
: this.state.defaultRedirectAddress + "/#/";
|
: this.state.defaultRedirectAddress + "/#/";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -770,20 +789,30 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
label="Username"
|
label="Username"
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="example@mastodon.example"
|
placeholder="example@mastodon.example"
|
||||||
onChange={(event) =>
|
onChange={event => this.updateUserInfo(event.target.value)}
|
||||||
this.updateUserInfo(event.target.value)
|
onKeyDown={event => this.watchUsernameField(event)}
|
||||||
}
|
|
||||||
onKeyDown={(event) => this.watchUsernameField(event)}
|
|
||||||
error={this.state.userInputError}
|
error={this.state.userInputError}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
<InputAdornment position="start">@</InputAdornment>
|
<InputAdornment position="start">@</InputAdornment>
|
||||||
),
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{this.state.userInputError ? (
|
{this.state.userInputError ? (
|
||||||
<Typography color="error">
|
<Typography color="error">
|
||||||
{this.state.userInputErrorMessage}
|
{this.state.userInputErrorMessage}
|
||||||
|
{this.state.userInputErrorMessage ===
|
||||||
|
"We couldn't recognize this instance." ? (
|
||||||
|
<span>
|
||||||
|
<br />
|
||||||
|
<Link
|
||||||
|
// className={classes.welcomeLink}
|
||||||
|
onClick={() => this.startLogin(true)}
|
||||||
|
>
|
||||||
|
Try anyway
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
</Typography>
|
</Typography>
|
||||||
) : null}
|
) : null}
|
||||||
<br />
|
<br />
|
||||||
|
@ -919,10 +948,10 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
label="Authorization code"
|
label="Authorization code"
|
||||||
fullWidth
|
fullWidth
|
||||||
onChange={(event) =>
|
onChange={event =>
|
||||||
this.updateAuthCode(event.target.value)
|
this.updateAuthCode(event.target.value)
|
||||||
}
|
}
|
||||||
onKeyDown={(event) => this.watchAuthField(event)}
|
onKeyDown={event => this.watchAuthField(event)}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
@ -974,8 +1003,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
<div
|
<div
|
||||||
className={classes.root}
|
className={classes.root}
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url(${this.state.backgroundUrl ?? "background.png"
|
backgroundImage: `url(${this.state.backgroundUrl ??
|
||||||
})`,
|
"background.png"})`
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paper className={classes.paper}>
|
<Paper className={classes.paper}>
|
||||||
|
@ -989,17 +1018,17 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
{this.state.authorizing
|
{this.state.authorizing
|
||||||
? this.showAuthorizationLoader()
|
? this.showAuthorizationLoader()
|
||||||
: this.state.proceedToGetCode
|
: this.state.proceedToGetCode
|
||||||
? this.showLoginAuth()
|
? this.showLoginAuth()
|
||||||
: getAccountRegistry().length > 0 &&
|
: getAccountRegistry().length > 0 &&
|
||||||
!this.state.willAddAccount
|
!this.state.willAddAccount
|
||||||
? this.showMultiAccount()
|
? this.showMultiAccount()
|
||||||
: this.showLanding()}
|
: this.showLanding()}
|
||||||
</Fade>
|
</Fade>
|
||||||
<br />
|
<br />
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
© {new Date().getFullYear()}{" "}
|
© {new Date().getFullYear()}{" "}
|
||||||
{this.state.brandName &&
|
{this.state.brandName &&
|
||||||
this.state.brandName !== "Hyperspace"
|
this.state.brandName !== "Hyperspace"
|
||||||
? `${this.state.brandName} developers and the `
|
? `${this.state.brandName} developers and the `
|
||||||
: ""}{" "}
|
: ""}{" "}
|
||||||
<Link
|
<Link
|
||||||
|
@ -1040,7 +1069,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
>
|
>
|
||||||
License
|
License
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
|
|
|{" "}
|
||||||
<Link
|
<Link
|
||||||
className={classes.welcomeLink}
|
className={classes.welcomeLink}
|
||||||
href="https://github.com/hyperspacedev/hyperspace/issues/new"
|
href="https://github.com/hyperspacedev/hyperspace/issues/new"
|
||||||
|
@ -1054,7 +1083,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||||
{this.state.brandName ?? "Hypersapce"} v.
|
{this.state.brandName ?? "Hypersapce"} v.
|
||||||
{this.state.version}{" "}
|
{this.state.version}{" "}
|
||||||
{this.state.brandName &&
|
{this.state.brandName &&
|
||||||
this.state.brandName !== "Hyperspace"
|
this.state.brandName !== "Hyperspace"
|
||||||
? "(Hyperspace-like)"
|
? "(Hyperspace-like)"
|
||||||
: null}
|
: null}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
Loading…
Reference in New Issue