-16
islands/Counter.tsx
-16
islands/Counter.tsx
···
1
-
import type { Signal } from "@preact/signals";
2
-
import { Button } from "../components/Button.tsx";
3
-
4
-
interface CounterProps {
5
-
count: Signal<number>;
6
-
}
7
-
8
-
export default function Counter(props: CounterProps) {
9
-
return (
10
-
<div class="flex gap-8 py-6">
11
-
<Button onClick={() => props.count.value -= 1}>-1</Button>
12
-
<p class="text-3xl tabular-nums">{props.count}</p>
13
-
<Button onClick={() => props.count.value += 1}>+1</Button>
14
-
</div>
15
-
);
16
-
}
···
+3
-2
islands/CredLogin.tsx
+3
-2
islands/CredLogin.tsx
···
1
import { useState } from 'preact/hooks'
2
import { JSX } from 'preact'
3
4
-
export default function CredLogin() {
5
const [handle, setHandle] = useState('')
6
const [password, setPassword] = useState('')
7
const [error, setError] = useState<string | null>(null)
···
32
await new Promise((resolve) => setTimeout(resolve, 500))
33
34
// Redirect to home page after successful login
35
-
globalThis.location.href = '/'
36
} catch (err) {
37
const message = err instanceof Error ? err.message : 'Login failed'
38
setError(message)
···
1
import { useState } from 'preact/hooks'
2
import { JSX } from 'preact'
3
+
import { LoginProps } from "./LoginSelector.tsx";
4
5
+
export default function CredLogin({ redirect }: LoginProps) {
6
const [handle, setHandle] = useState('')
7
const [password, setPassword] = useState('')
8
const [error, setError] = useState<string | null>(null)
···
33
await new Promise((resolve) => setTimeout(resolve, 500))
34
35
// Redirect to home page after successful login
36
+
globalThis.location.href = '/login/callback?redirect=' + encodeURIComponent(redirect)
37
} catch (err) {
38
const message = err instanceof Error ? err.message : 'Login failed'
39
setError(message)
+5
-3
islands/Ticket.tsx
+5
-3
islands/Ticket.tsx
···
63
</p>
64
<p>
65
Think you might need to migrate in the future but your PDS might be
66
-
hostile or offline? No worries! You can head to the ticket booth and
67
-
get a PLC key free of charge and use it for account recovery in the
68
-
future. You can also go to baggage claim (take the air shuttle to
69
terminal four) and get a downloadable backup of all your current PDS
70
data in case that were to happen.
71
</p>
···
63
</p>
64
<p>
65
Think you might need to migrate in the future but your PDS might be
66
+
hostile or offline? No worries! Soon you'll be able to go to the
67
+
ticket booth and get a PLC key free of charge and use it for account
68
+
recovery in the future. You can also go to baggage claim (take the air
69
+
shuttle to terminal four) and get a downloadable backup of all your
70
+
current PDS data in case that were to happen.
71
terminal four) and get a downloadable backup of all your current PDS
72
data in case that were to happen.
73
</p>
+17
-3
main.ts
+17
-3
main.ts
···
8
app.use(staticFiles());
9
10
// this can also be defined via a file. feel free to delete this!
11
-
const exampleLoggerMiddleware = define.middleware((ctx) => {
12
-
console.log(`${ctx.req.method} ${ctx.req.url}`);
13
return ctx.next();
14
});
15
-
app.use(exampleLoggerMiddleware);
16
17
await fsRoutes(app, {
18
loadIsland: (path) => import(`./islands/${path}`),
···
8
app.use(staticFiles());
9
10
// this can also be defined via a file. feel free to delete this!
11
+
const authMiddleware = define.middleware(async (ctx) => {
12
+
const url = new URL(ctx.req.url);
13
+
if (url.pathname.startsWith("/migrate")) {
14
+
ctx.state.auth = true
15
+
}
16
+
if (ctx.state.auth) {
17
+
const me = await fetch(`${url.origin}/api/me`, {
18
+
credentials: "include",
19
+
});
20
+
const json = await me.json();
21
+
if (json !== null && json.did) {
22
+
return ctx.next();
23
+
} else {
24
+
return ctx.redirect("/login");
25
+
}
26
+
}
27
return ctx.next();
28
});
29
+
app.use(authMiddleware);
30
31
await fsRoutes(app, {
32
loadIsland: (path) => import(`./islands/${path}`),
+1
-1
routes/index.tsx
+1
-1
routes/index.tsx
···
28
/>
29
</div>
30
<p class="font-mono text-lg sm:text-xl mb-4 mt-4 sm:mb-6 mt-0 text-center text-gray-600 dark:text-gray-300">
31
-
Airport is made with love by <a class="text-blue-500 hover:underline" href="https://bsky.app/profile/knotbin.com">Roscoe</a> in collaboration with <a class="text-blue-500 hover:underline" href="https://sprk.so">Spark</a>.
32
</p>
33
<SocialLinks />
34
</div>
···
28
/>
29
</div>
30
<p class="font-mono text-lg sm:text-xl mb-4 mt-4 sm:mb-6 mt-0 text-center text-gray-600 dark:text-gray-300">
31
+
Airport is made with love by <a class="text-blue-500 hover:underline" href="https://bsky.app/profile/knotbin.com">Roscoe</a> for <a class="text-blue-500 hover:underline" href="https://sprk.so">Spark</a>, a new short-video platform for AT Protocol.
32
</p>
33
<SocialLinks />
34
</div>
+4
-2
utils.ts
+4
-2
utils.ts