···44import { Text } from "@/components/ui/text";
55import { Button } from "@/components/ui/button";
66import { Icon } from "@/lib/icons/iconWithClassName";
77-import { ArrowRight } from "lucide-react-native";
77+import { ArrowRight, Info } from "lucide-react-native";
8899import { Stack, router } from "expo-router";
1010import { FontAwesome6 } from "@expo/vector-icons";
···3434 <Text className="text-foreground text-lg">
3535 No account? That's fine.
3636 </Text>
3737- <Text className="text-foreground mb-4 text-center text-lg">
3737+ <Text className="text-foreground text-center text-lg">
3838 Sign up for Bluesky, then return here to sign in.
3939+ </Text>
4040+ <Text className="text-muted-foreground mt-2 mb-4 text-center text-xs">
4141+ You'll need a PDS to use teal.fm. Bluesky is a good way to get one.
3942 </Text>
4043 {/* on click, open tab, then in the background navigate to /login */}
4144 <Button
+3-2
apps/amethyst/lib/atp/oauth.tsx
···1212>;
13131414export default function createOAuthClient(
1515- baseUrl: string
1515+ baseUrl: string,
1616+ pdsBaseUrl: string,
1617): AquareumOAuthClient {
1718 if (!baseUrl) {
1819 throw new Error("baseUrl is required");
···6061 };
6162 clientMetadataSchema.parse(meta);
6263 return new ReactNativeOAuthClient({
6363- handleResolver: "https://bsky.social", // backend instances should use a DNS based resolver
6464+ handleResolver: "https://" + pdsBaseUrl, // backend instances should use a DNS based resolver
6465 responseMode: "query", // or "fragment" (frontend only) or "form_post" (backend only)
65666667 // These must be the same metadata as the one exposed on the
+70-62
apps/amethyst/lib/atp/pid.ts
···5566// resolve pid
77export const isDid = (did: string) => {
88- // is this a did? regex
99- return did.match(/^did:[a-z]+:[\S\s]+/)
1010-}
88+ // is this a did? regex
99+ return did.match(/^did:[a-z]+:[\S\s]+/);
1010+};
11111212-export const resolveHandle = async (handle: string, resolverAppViewUrl: string = "https://public.api.bsky.app"): Promise<string> => {
1313- const url = resolverAppViewUrl + `/xrpc/com.atproto.identity.resolveHandle` + `?handle=${handle}`;
1212+export const resolveHandle = async (
1313+ handle: string,
1414+ resolverAppViewUrl: string = "https://public.api.bsky.app",
1515+): Promise<string> => {
1616+ const url =
1717+ resolverAppViewUrl +
1818+ `/xrpc/com.atproto.identity.resolveHandle` +
1919+ `?handle=${handle}`;
14201515- const response = await fetch(url);
1616- if (response.status === 400) {
1717- throw new Error(`domain handle not found`);
1818- } else if (!response.ok) {
1919- throw new Error(`directory is unreachable`);
2020- }
2121+ const response = await fetch(url);
2222+ if (response.status === 400) {
2323+ throw new Error(`domain handle not found`);
2424+ } else if (!response.ok) {
2525+ throw new Error(`directory is unreachable`);
2626+ }
21272222- const json = (await response.json())
2323- return json.did;
2828+ const json = await response.json();
2929+ return json.did;
2430};
25312626-2727-2832export const getDidDocument = async (did: string) => {
2929- const colon_index = did.indexOf(':', 4);
3333+ const colon_index = did.indexOf(":", 4);
30343131- const type = did.slice(4, colon_index);
3232- const ident = did.slice(colon_index + 1);
3535+ const type = did.slice(4, colon_index);
3636+ const ident = did.slice(colon_index + 1);
33373434- // get a did:plc
3535- if (type === 'plc') {
3636- const res = await fetch("https://plc.directory/" + did)
3838+ // get a did:plc
3939+ if (type === "plc") {
4040+ const res = await fetch("https://plc.directory/" + did);
37413838- if (res.status === 400) {
3939- throw new Error(`domain handle not found`);
4040- } else if (!res.ok) {
4141- throw new Error(`directory is unreachable`);
4242- }
4343-4444- const json = (await res.json())
4545- return json;
4646- } else if (type === "web") {
4747- if (ident.match(/^([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))$/)) {
4848- throw new Error(`invalid domain handle`);
4949- }
5050- const res = await fetch(`https://${ident}/.well-known/did.json`);
4242+ if (res.status === 400) {
4343+ throw new Error(`domain handle not found`);
4444+ } else if (!res.ok) {
4545+ throw new Error(`directory is unreachable`);
4646+ }
51475252- if (res.status === 400) {
5353- throw new Error(`domain handle not found`);
5454- }
5555- else if (!res.ok) {
5656- throw new Error(`directory is unreachable`);
5757- }
4848+ const json = await res.json();
4949+ return json;
5050+ } else if (type === "web") {
5151+ if (
5252+ !ident.match(/^([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))$/)
5353+ ) {
5454+ throw new Error(`invalid domain handle`);
5555+ }
5656+ const res = await fetch(`https://${ident}/.well-known/did.json`);
58575959- const json = await res.json();
6060- return json;
5858+ if (res.status === 400) {
5959+ throw new Error(`domain handle not found`);
6060+ } else if (!res.ok) {
6161+ throw new Error(`directory is unreachable`);
6162 }
6262-6363-6363+6464+ const json = await res.json();
6565+ return json;
6666+ }
6467};
65686666-export const resolveFromIdentity = async(identity: string, resolverAppViewUrl: string = "https://public.api.bsky.app") => {
6767- let did: string
6868- // is this a did? regex
6969- if (isDid(identity)) {
7070- did = identity
7171- } else {
7272- did = await resolveHandle(identity, resolverAppViewUrl)
7373- }
6969+export const resolveFromIdentity = async (
7070+ identity: string,
7171+ resolverAppViewUrl: string = "https://public.api.bsky.app",
7272+) => {
7373+ let did: string;
7474+ // is this a did? regex
7575+ if (isDid(identity)) {
7676+ did = identity;
7777+ } else {
7878+ did = await resolveHandle(identity, resolverAppViewUrl);
7979+ }
74807575- let doc = await getDidDocument(did)
7676- let pds = getPdsEndpoint(doc)
8181+ let doc = await getDidDocument(did);
8282+ let pds = getPdsEndpoint(doc);
77837878- if (!pds) {
7979- throw new Error("account doesn't have PDS endpoint?")
8080- }
8484+ if (!pds) {
8585+ throw new Error("account doesn't have PDS endpoint?");
8686+ }
81878282- return {
8383- did,doc,identity,
8484- pds: new URL(pds),
8585- }
8686-}8888+ return {
8989+ did,
9090+ doc,
9191+ identity,
9292+ pds: new URL(pds),
9393+ };
9494+};