commit
2e70cc09f6
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.0.0beta2",
|
||||
"version": "1.0.0beta2u1",
|
||||
"location": "https://hyperspaceapp-next.herokuapp.com",
|
||||
"branding": {
|
||||
"name": "Hyperspace",
|
||||
|
|
|
@ -508,7 +508,7 @@ export class Post extends React.Component<any, IPostState> {
|
|||
</Tooltip>
|
||||
<Typography>{post.reblog? post.reblog.reblogs_count: post.reblogs_count}</Typography>
|
||||
<Tooltip className={classes.desktopOnly} title="View thread">
|
||||
<LinkableIconButton to={`/conversation/${post.id}`}>
|
||||
<LinkableIconButton to={`/conversation/${post.reblog? post.reblog.id: post.id}`}>
|
||||
<ForumIcon />
|
||||
</LinkableIconButton>
|
||||
</Tooltip>
|
||||
|
@ -550,7 +550,7 @@ export class Post extends React.Component<any, IPostState> {
|
|||
}
|
||||
<div className={classes.mobileOnly}>
|
||||
<Divider/>
|
||||
<LinkableMenuItem to={`/conversation/${post.id}`}>View thread</LinkableMenuItem>
|
||||
<LinkableMenuItem to={`/conversation/${post.reblog? post.reblog.id: post.id}`}>View thread</LinkableMenuItem>
|
||||
<MenuItem component="a" href={this.getMastodonUrl(post)} rel="noreferrer" target="_blank">Open in Web</MenuItem>
|
||||
</div>
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import {withStyles, Paper, Typography, Button, TextField, Fade, Link, CircularProgress, Tooltip} from '@material-ui/core';
|
||||
import {withStyles, Paper, Typography, Button, TextField, Fade, Link, CircularProgress, Tooltip, Dialog, DialogTitle, DialogActions, DialogContent} from '@material-ui/core';
|
||||
import {styles} from './WelcomePage.styles';
|
||||
import Mastodon from 'megalodon';
|
||||
import {SaveClientSession} from '../types/SessionData';
|
||||
|
@ -7,6 +7,11 @@ import { createHyperspaceApp } from '../utilities/login';
|
|||
import {parseUrl} from 'query-string';
|
||||
import { getConfig } from '../utilities/settings';
|
||||
import axios from 'axios';
|
||||
import {withSnackbar, withSnackbarProps} from 'notistack';
|
||||
|
||||
interface IWelcomeProps extends withSnackbarProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
interface IWelcomeState {
|
||||
logoUrl?: string;
|
||||
|
@ -26,9 +31,12 @@ interface IWelcomeState {
|
|||
license?: string;
|
||||
repo?: string;
|
||||
defaultRedirectAddress: string;
|
||||
openAuthDialog: boolean;
|
||||
authCode: string;
|
||||
emergencyMode: boolean;
|
||||
}
|
||||
|
||||
class WelcomePage extends Component<any, IWelcomeState> {
|
||||
class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
|
||||
client: any;
|
||||
|
||||
|
@ -42,7 +50,10 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
foundSavedLogin: false,
|
||||
authority: false,
|
||||
userInputErrorMessage: '',
|
||||
defaultRedirectAddress: ''
|
||||
defaultRedirectAddress: '',
|
||||
openAuthDialog: false,
|
||||
authCode: '',
|
||||
emergencyMode: false
|
||||
}
|
||||
|
||||
getConfig().then((result: any) => {
|
||||
|
@ -64,44 +75,62 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
})
|
||||
}
|
||||
|
||||
updateUserInfo(user: string) {
|
||||
this.setState({ user });
|
||||
}
|
||||
|
||||
updateAuthCode(code: string) {
|
||||
this.setState({ authCode: code });
|
||||
}
|
||||
|
||||
toggleAuthDialog() {
|
||||
this.setState({ openAuthDialog: !this.state.openAuthDialog });
|
||||
}
|
||||
|
||||
readyForAuth() {
|
||||
if (localStorage.getItem('baseurl')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem("login")) {
|
||||
this.getSavedSession();
|
||||
this.setState({
|
||||
foundSavedLogin: true
|
||||
})
|
||||
this.getSavedSession();
|
||||
this.checkForToken();
|
||||
}
|
||||
}
|
||||
|
||||
checkForToken() {
|
||||
let location = window.location.href;
|
||||
if (location.includes("?code=")) {
|
||||
let code = parseUrl(location).query.code as string;
|
||||
this.setState({ authority: true });
|
||||
let loginData = localStorage.getItem("login");
|
||||
|
||||
if (loginData) {
|
||||
let clientLoginSession: SaveClientSession = JSON.parse(loginData);
|
||||
console.log(clientLoginSession);
|
||||
Mastodon.fetchAccessToken(
|
||||
clientLoginSession.clientId,
|
||||
clientLoginSession.clientSecret,
|
||||
code,
|
||||
(localStorage.getItem("baseurl") as string),
|
||||
`https://${window.location.host}`,
|
||||
).then((tokenData: any) => {
|
||||
localStorage.setItem("access_token", tokenData.access_token);
|
||||
window.location.href=`https://${window.location.host}/#/`;
|
||||
}).catch((err: Error) => {
|
||||
console.log(err.message);
|
||||
})
|
||||
}
|
||||
getSavedSession() {
|
||||
let loginData = localStorage.getItem("login");
|
||||
if (loginData) {
|
||||
let session: SaveClientSession = JSON.parse(loginData);
|
||||
this.setState({
|
||||
clientId: session.clientId,
|
||||
clientSecret: session.clientSecret,
|
||||
authUrl: session.authUrl,
|
||||
emergencyMode: session.emergency
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
updateUserInfo(user: string) {
|
||||
this.setState({ user });
|
||||
startEmergencyLogin() {
|
||||
if (!this.state.emergencyMode) {
|
||||
this.createEmergencyLogin();
|
||||
};
|
||||
this.toggleAuthDialog();
|
||||
}
|
||||
|
||||
startRegistration() {
|
||||
if (this.state.registerBase) {
|
||||
return "https://" + this.state.registerBase + "/auth/sign_up";
|
||||
} else {
|
||||
return "https://joinmastodon.org/#getting-started";
|
||||
}
|
||||
}
|
||||
|
||||
getLoginUser(user: string) {
|
||||
|
@ -116,14 +145,6 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
}
|
||||
}
|
||||
|
||||
startRegistration() {
|
||||
if (this.state.registerBase) {
|
||||
return "https://" + this.state.registerBase + "/auth/sign_up";
|
||||
} else {
|
||||
return "https://joinmastodon.org/#getting-started";
|
||||
}
|
||||
}
|
||||
|
||||
startLogin() {
|
||||
let error = this.checkForErrors();
|
||||
if (!error) {
|
||||
|
@ -134,7 +155,8 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
let saveSessionForCrashing: SaveClientSession = {
|
||||
clientId: resp.clientId,
|
||||
clientSecret: resp.clientSecret,
|
||||
authUrl: resp.url
|
||||
authUrl: resp.url,
|
||||
emergency: false
|
||||
}
|
||||
localStorage.setItem("login", JSON.stringify(saveSessionForCrashing));
|
||||
this.setState({
|
||||
|
@ -149,6 +171,30 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
}
|
||||
}
|
||||
|
||||
createEmergencyLogin() {
|
||||
console.log("Creating an emergency login...")
|
||||
const scopes = "read write follow";
|
||||
const baseurl = localStorage.getItem('baseurl') || this.getLoginUser(this.state.user);
|
||||
createHyperspaceApp(scopes, baseurl, "urn:ietf:wg:oauth:2.0:oob").then((resp: any) => {
|
||||
let saveSessionForCrashing: SaveClientSession = {
|
||||
clientId: resp.clientId,
|
||||
clientSecret: resp.clientSecret,
|
||||
authUrl: resp.url,
|
||||
emergency: true
|
||||
};
|
||||
localStorage.setItem("login", JSON.stringify(saveSessionForCrashing));
|
||||
this.setState({
|
||||
clientId: resp.clientId,
|
||||
clientSecret: resp.clientSecret,
|
||||
authUrl: resp.url
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
authorizeEmergencyLogin() {
|
||||
window.location.href = `/?code=${this.state.authCode}#/`;
|
||||
}
|
||||
|
||||
resumeLogin() {
|
||||
let loginData = localStorage.getItem("login");
|
||||
if (loginData) {
|
||||
|
@ -157,23 +203,12 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
clientId: session.clientId,
|
||||
clientSecret: session.clientSecret,
|
||||
authUrl: session.authUrl,
|
||||
emergencyMode: session.emergency,
|
||||
wantsToLogin: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getSavedSession() {
|
||||
let loginData = localStorage.getItem("login");
|
||||
if (loginData) {
|
||||
let session: SaveClientSession = JSON.parse(loginData);
|
||||
this.setState({
|
||||
clientId: session.clientId,
|
||||
clientSecret: session.clientSecret,
|
||||
authUrl: session.authUrl
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
checkForErrors(): boolean {
|
||||
let userInputError = false;
|
||||
let userInputErrorMessage = "";
|
||||
|
@ -201,11 +236,32 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
|
||||
}
|
||||
|
||||
readyForAuth() {
|
||||
if (localStorage.getItem('baseurl')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
checkForToken() {
|
||||
let location = window.location.href;
|
||||
if (location.includes("?code=")) {
|
||||
let code = parseUrl(location).query.code as string;
|
||||
this.setState({ authority: true });
|
||||
let loginData = localStorage.getItem("login");
|
||||
if (loginData) {
|
||||
let clientLoginSession: SaveClientSession = JSON.parse(loginData);
|
||||
Mastodon.fetchAccessToken(
|
||||
clientLoginSession.clientId,
|
||||
clientLoginSession.clientSecret,
|
||||
code,
|
||||
(localStorage.getItem("baseurl") as string),
|
||||
this.state.emergencyMode?
|
||||
undefined:
|
||||
clientLoginSession.authUrl.includes("urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob")?
|
||||
undefined:
|
||||
`https://${window.location.host}`,
|
||||
).then((tokenData: any) => {
|
||||
localStorage.setItem("access_token", tokenData.access_token);
|
||||
window.location.href=`https://${window.location.host}/#/`;
|
||||
}).catch((err: Error) => {
|
||||
this.props.enqueueSnackbar("Couldn't authorize Hyperspace: " + err.name, {variant: 'error'});
|
||||
console.error(err.message);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,10 +336,51 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
<div className={classes.flexGrow}/>
|
||||
</div>
|
||||
<div className={classes.middlePadding}/>
|
||||
<Typography>Having trouble signing in? <Link onClick={() => this.startEmergencyLogin()}>Sign in with a code.</Link></Typography>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
showAuthDialog() {
|
||||
const {classes} = this.props;
|
||||
return (
|
||||
<Dialog
|
||||
open={this.state.openAuthDialog}
|
||||
disableBackdropClick
|
||||
disableEscapeKeyDown
|
||||
maxWidth="sm"
|
||||
fullWidth={true}
|
||||
>
|
||||
<DialogTitle>
|
||||
Authorize with a code
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography paragraph>
|
||||
If you're having trouble authorizing Hyperspace, you can manually request for an authorization code. Click 'Request Code' and then paste the code in the authorization code box to continue.
|
||||
</Typography>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
href={this.state.authUrl? this.state.authUrl: ""}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Request Code</Button>
|
||||
<br/><br/>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
label="Authorization code"
|
||||
fullWidth
|
||||
onChange={(event) => this.updateAuthCode(event.target.value)}
|
||||
></TextField>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => this.toggleAuthDialog()}>Cancel</Button>
|
||||
<Button color="secondary" onClick={() => this.authorizeEmergencyLogin()}>Authorize</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
showAuthority() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
|
@ -325,9 +422,10 @@ class WelcomePage extends Component<any, IWelcomeState> {
|
|||
{ this.state.repo? <span><Link href={this.state.repo? this.state.repo: "https://github.com/hyperspacedev"} target="_blank" rel="noreferrer">Source code</Link> | </span>: null}<Link href={this.state.license? this.state.license: "https://www.apache.org/licenses/LICENSE-2.0"} target="_blank" rel="noreferrer">License</Link> | <Link href="https://github.com/hyperspacedev/hyperspace/issues/new" target="_blank" rel="noreferrer">File an Issue</Link>
|
||||
</Typography>
|
||||
</Paper>
|
||||
{this.showAuthDialog()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(WelcomePage);
|
||||
export default withStyles(styles)(withSnackbar(WelcomePage));
|
|
@ -2,4 +2,5 @@ export type SaveClientSession = {
|
|||
clientId: string;
|
||||
clientSecret: string;
|
||||
authUrl: string;
|
||||
emergency: boolean;
|
||||
}
|
Loading…
Reference in New Issue