Archived
1
0

Generalize initial app logic

This commit is contained in:
Asher
2020-02-05 18:47:00 -06:00
parent 205775ac97
commit 6cebfa469d
9 changed files with 78 additions and 57 deletions

View File

@ -1,5 +1,12 @@
import { getBasepath } from "hookrouter"
import { Application, ApplicationsResponse, CreateSessionResponse, FilesResponse, RecentResponse } from "../common/api"
import {
Application,
ApplicationsResponse,
CreateSessionResponse,
FilesResponse,
LoginResponse,
RecentResponse,
} from "../common/api"
import { ApiEndpoint, HttpCode, HttpError } from "../common/http"
export interface AuthBody {
@ -33,7 +40,7 @@ const tryRequest = async (endpoint: string, options?: RequestInit): Promise<Resp
/**
* Try authenticating.
*/
export const authenticate = async (body?: AuthBody): Promise<void> => {
export const authenticate = async (body?: AuthBody): Promise<LoginResponse> => {
const response = await tryRequest(ApiEndpoint.login, {
method: "POST",
body: JSON.stringify({ ...body, basePath: getBasepath() }),
@ -41,10 +48,7 @@ export const authenticate = async (body?: AuthBody): Promise<void> => {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
},
})
const json = await response.json()
if (json && json.success) {
setAuthed(true)
}
return response.json()
}
export const getFiles = async (): Promise<FilesResponse> => {

View File

@ -10,34 +10,33 @@ export interface AppProps {
options: Options
}
interface RedirectedApplication extends Application {
redirected?: boolean
}
const origin = typeof window !== "undefined" ? window.location.origin + window.location.pathname : undefined
const App: React.FunctionComponent<AppProps> = (props) => {
const [authed, setAuthed] = React.useState<boolean>(props.options.authed)
const [app, setApp] = React.useState<Application | undefined>(props.options.app)
const [app, setApp] = React.useState<RedirectedApplication | undefined>(props.options.app)
const [error, setError] = React.useState<HttpError | Error | string>()
if (typeof window !== "undefined") {
const url = new URL(window.location.origin + window.location.pathname + props.options.basePath)
const url = new URL(origin + props.options.basePath)
setBasepath(normalize(url.pathname))
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(window as any).setAuthed = (a: boolean): void => {
if (authed !== a) {
setAuthed(a)
// TEMP: Remove when no longer auto-loading VS Code.
if (a && !app) {
setApp({
name: "VS Code",
path: "/",
embedPath: "/vscode-embed",
})
}
}
}
}
React.useEffect(() => {
if (app && !isExecutableApplication(app)) {
if (app && !isExecutableApplication(app) && !app.redirected) {
navigate(normalize(`${getBasepath()}/${app.path}/`, true))
setApp({ ...app, redirected: true })
}
}, [app])
@ -51,7 +50,7 @@ const App: React.FunctionComponent<AppProps> = (props) => {
undefined
)}
<Modal app={app} setApp={setApp} authed={authed} error={error} setError={setError} />
{authed && app && app.embedPath ? (
{authed && app && app.embedPath && app.redirected ? (
<iframe id="iframe" src={normalize(`./${app.embedPath}/`, true)}></iframe>
) : (
undefined

View File

@ -22,7 +22,6 @@ export interface ModalProps {
enum Section {
Browse,
Home,
Login,
Open,
Recent,
}
@ -103,7 +102,7 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
const content = (): React.ReactElement => {
if (!props.authed) {
return <Login />
return <Login setApp={setApp} />
}
switch (section) {
case Section.Recent:
@ -112,8 +111,6 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
return <Home app={props.app} />
case Section.Browse:
return <Browse />
case Section.Login:
return <Login />
case Section.Open:
return <Open app={props.app} setApp={setApp} />
default:
@ -140,9 +137,7 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
</button>
</>
) : (
<button className="link" onClick={(): void => setSection(Section.Login)}>
Login
</button>
undefined
)}
</nav>
<div className="footer">

View File

@ -1,6 +1,6 @@
import * as React from "react"
import { Application } from "../../common/api"
import { authenticate } from "../api"
import { authenticate, setAuthed } from "../api"
export interface HomeProps {
app?: Application
@ -8,7 +8,9 @@ export interface HomeProps {
export const Home: React.FunctionComponent<HomeProps> = (props) => {
React.useEffect(() => {
authenticate().catch(() => undefined)
authenticate()
.then(() => setAuthed(true))
.catch(() => undefined)
}, [])
return (

View File

@ -1,22 +1,36 @@
import * as React from "react"
import { Application } from "../../common/api"
import { HttpError } from "../../common/http"
import { authenticate } from "../api"
import { authenticate, setAuthed } from "../api"
import { FieldError } from "../components/error"
export interface LoginProps {
setApp(app: Application): void
}
/**
* Login page. Will redirect on success.
*/
export const Login: React.FunctionComponent = () => {
export const Login: React.FunctionComponent<LoginProps> = (props) => {
const [password, setPassword] = React.useState<string>("")
const [error, setError] = React.useState<HttpError>()
async function handleSubmit(event: React.FormEvent<HTMLFormElement>): Promise<void> {
event.preventDefault()
authenticate({ password }).catch(setError)
authenticate({ password })
.then((response) => {
if (response.app) {
props.setApp(response.app)
}
setAuthed(true)
})
.catch(setError)
}
React.useEffect(() => {
authenticate().catch(() => undefined)
authenticate()
.then(() => setAuthed(true))
.catch(() => undefined)
}, [])
return (