import React, { Component } from 'react'; import {withStyles, Paper, Typography, Button, TextField, Fade, Link, CircularProgress, Tooltip} from '@material-ui/core'; import {styles} from './WelcomePage.styles'; import Mastodon from 'megalodon'; import {SaveClientSession} from '../types/SessionData'; import { createHyperspaceApp } from '../utilities/login'; import {parseUrl} from 'query-string'; import { getConfig } from '../utilities/settings'; import axios from 'axios'; interface IWelcomeState { logoUrl?: string; backgroundUrl?: string; brandName?: string; registerBase?: string; federates?: boolean; wantsToLogin: boolean; user: string; userInputError: boolean; userInputErrorMessage: string; clientId?: string; clientSecret?: string; authUrl?: string; foundSavedLogin: boolean; authority: boolean; license?: string; repo?: string; defaultRedirectAddress: string; } class WelcomePage extends Component { client: any; constructor(props: any) { super(props); this.state = { wantsToLogin: false, user: "", userInputError: false, foundSavedLogin: false, authority: false, userInputErrorMessage: '', defaultRedirectAddress: '' } getConfig().then((result: any) => { if (result.location === "dynamic") { console.warn("Recirect URI is set to dyanmic, which may affect how sign-in works for some users. Careful!"); } this.setState({ logoUrl: result.branding? result.branding.logo: "logo.png", backgroundUrl: result.branding? result.branding.background: "background.png", brandName: result.branding? result.branding.name: "Hyperspace", registerBase: result.registration? result.registration.defaultInstance: "", federates: result.federated? result.federated === "true": true, license: result.license.url, repo: result.repository, defaultRedirectAddress: result.location != "dynamic"? result.location: `https://${window.location.host}` }); }).catch(() => { console.error('config.json is missing. If you want to customize Hyperspace, please include config.json'); }) } componentDidMount() { if (localStorage.getItem("login")) { 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); }) } } } updateUserInfo(user: string) { this.setState({ user }); } getLoginUser(user: string) { if (user.includes("@")) { let newUser = user; this.setState({ user: newUser }) return "https://" + newUser.split("@")[1]; } else { let newUser = `${user}@${this.state.registerBase? this.state.registerBase: "mastodon.social"}`; this.setState({ user: newUser }); return "https://" + (this.state.registerBase? this.state.registerBase: "mastodon.social"); } } 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) { const scopes = 'read write follow'; const baseurl = this.getLoginUser(this.state.user); localStorage.setItem("baseurl", baseurl); createHyperspaceApp(scopes, baseurl, this.state.defaultRedirectAddress).then((resp: any) => { let saveSessionForCrashing: SaveClientSession = { clientId: resp.clientId, clientSecret: resp.clientSecret, authUrl: resp.url } localStorage.setItem("login", JSON.stringify(saveSessionForCrashing)); this.setState({ clientId: resp.clientId, clientSecret: resp.clientSecret, authUrl: resp.url, wantsToLogin: true }) }) } else { } } resumeLogin() { let loginData = localStorage.getItem("login"); if (loginData) { let session: SaveClientSession = JSON.parse(loginData); this.setState({ clientId: session.clientId, clientSecret: session.clientSecret, authUrl: session.authUrl, 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 = ""; if (this.state.user === "") { userInputError = true; userInputErrorMessage = "Username cannot be blank."; this.setState({ userInputError, userInputErrorMessage }); return true; } else { if (this.state.user.includes("@")) { let baseUrl = this.state.user.split("@")[1]; axios.get("https://" + baseUrl + "/api/v1/timelines/public").catch((err: Error) => { let userInputError = true; let userInputErrorMessage = "Instance name is invalid."; this.setState({ userInputError, userInputErrorMessage }); return true; }) } else { this.setState({ userInputError, userInputErrorMessage }); return false; } return false; } } readyForAuth() { if (localStorage.getItem('baseurl')) { return true; } else { return false; } } showLanding() { const { classes } = this.props; return (
Sign in with your Mastodon account
this.updateUserInfo(event.target.value)} error={this.state.userInputError} onBlur={() => this.checkForErrors()} > { this.state.userInputError? {this.state.userInputErrorMessage} : null }
{ this.state.registerBase? If you are from {this.state.registerBase? this.state.registerBase: "noinstance"}, sign in with your username.: null }
{ this.state.foundSavedLogin? Signing in from a previous session? this.resumeLogin()}>Continue login. : null }
); } showLoginAuth() { const { classes } = this.props; return (
Howdy, {this.state.user? this.state.user.split("@")[0]: "user"} To continue, finish signing in on your instance's website and authorize Hyperspace.
); } showAuthority() { const { classes } = this.props; return (
Authorizing Please wait while Hyperspace authorizes with Mastodon. This shouldn't take long...
); } render() { const { classes } = this.props; return (
{this.state?
{ this.state.authority? this.showAuthority(): this.state.wantsToLogin? this.showLoginAuth(): this.showLanding() }
© 2019 Hyperspace developers. All rights reserved. { this.state.repo? Source code | : null}License | File an Issue
); } } export default withStyles(styles)(WelcomePage);