swap from stores to states

This commit is contained in:
Badtz 2025-03-31 19:22:09 -07:00
parent 4c14a1ce89
commit aeee9019ab
8 changed files with 149 additions and 14 deletions

View file

@ -8,6 +8,7 @@
"@atcute/identity": "^0.1.2", "@atcute/identity": "^0.1.2",
"@atcute/identity-resolver": "^0.1.2", "@atcute/identity-resolver": "^0.1.2",
"@atcute/lex-cli": "^1.0.4", "@atcute/lex-cli": "^1.0.4",
"@atcute/oauth-browser-client": "^1.0.16",
"@eslint/compat": "^1.2.5", "@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0", "@eslint/js": "^9.18.0",
"@iconify-json/mynaui": "^1.2.9", "@iconify-json/mynaui": "^1.2.9",
@ -49,6 +50,12 @@
"@atcute/lex-cli": ["@atcute/lex-cli@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.3.11", "@externdefs/collider": "^0.1.0", "picocolors": "^1.1.1", "prettier": "^3.3.3" }, "bin": { "lex-cli": "cli.mjs" } }, "sha512-8mRnjjK+b6Z4wmfFRUYYPswVZhT7PYZBHLMCFNiI1AdrZqaJ1CmoiExYjkVGQkixZURRIaxr49KGBV2iSMF/pQ=="], "@atcute/lex-cli": ["@atcute/lex-cli@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.3.11", "@externdefs/collider": "^0.1.0", "picocolors": "^1.1.1", "prettier": "^3.3.3" }, "bin": { "lex-cli": "cli.mjs" } }, "sha512-8mRnjjK+b6Z4wmfFRUYYPswVZhT7PYZBHLMCFNiI1AdrZqaJ1CmoiExYjkVGQkixZURRIaxr49KGBV2iSMF/pQ=="],
"@atcute/multibase": ["@atcute/multibase@1.1.2", "", { "dependencies": { "@atcute/uint8array": "^1.0.1" } }, "sha512-KFX+c7a/u2jSNcRw0rLaUHG/XEKf1A1c8XF5soHnsb1JMCShihf/anfZ1kJ4no/IlIp9HEHV3PQRQO2sWL6ASQ=="],
"@atcute/oauth-browser-client": ["@atcute/oauth-browser-client@1.0.16", "", { "dependencies": { "@atcute/client": "^2.0.9", "@atcute/multibase": "^1.1.2", "@atcute/uint8array": "^1.0.1" } }, "sha512-BKkA4TPyaLIO+hVxcxZoDfLFUgsd3A47UyzWAbe3BpSoN8Kywy/CqWuAVlqdiUhO1iG+vVqGQhjKy4UxutaU4g=="],
"@atcute/uint8array": ["@atcute/uint8array@1.0.1", "", {}, "sha512-AAnlFKyfDRgb9GNZJbhQ6OuMhbmNPirQyapb8KnmcEhxQZ3+tt+4NcwqekEegY4MpNqSTYeeTdyxq0wGZv1JHg=="],
"@atcute/util-fetch": ["@atcute/util-fetch@1.0.1", "", { "dependencies": { "@badrap/valita": "^0.4.2" } }, "sha512-Clc0E/5ufyGBVfYBUwWNlHONlZCoblSr4Ho50l1LhmRPGB1Wu/AQ9Sz+rsBg7fdaW/auve8ulmwhRhnX2cGRow=="], "@atcute/util-fetch": ["@atcute/util-fetch@1.0.1", "", { "dependencies": { "@badrap/valita": "^0.4.2" } }, "sha512-Clc0E/5ufyGBVfYBUwWNlHONlZCoblSr4Ho50l1LhmRPGB1Wu/AQ9Sz+rsBg7fdaW/auve8ulmwhRhnX2cGRow=="],
"@badrap/valita": ["@badrap/valita@0.4.3", "", {}, "sha512-C9iZSrVlTb610dxZ2oatK5LwefaHv0Q9eYfVDH3co846x7WinhCfc8jCDTE55yM8WxlmOfX2ckKmsSr7KzZ/gg=="], "@badrap/valita": ["@badrap/valita@0.4.3", "", {}, "sha512-C9iZSrVlTb610dxZ2oatK5LwefaHv0Q9eYfVDH3co846x7WinhCfc8jCDTE55yM8WxlmOfX2ckKmsSr7KzZ/gg=="],

View file

@ -20,6 +20,7 @@
"@atcute/identity": "^0.1.2", "@atcute/identity": "^0.1.2",
"@atcute/identity-resolver": "^0.1.2", "@atcute/identity-resolver": "^0.1.2",
"@atcute/lex-cli": "^1.0.4", "@atcute/lex-cli": "^1.0.4",
"@atcute/oauth-browser-client": "^1.0.16",
"@eslint/compat": "^1.2.5", "@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0", "@eslint/js": "^9.18.0",
"@iconify-json/mynaui": "^1.2.9", "@iconify-json/mynaui": "^1.2.9",

12
src/lib/state.svelte.ts Normal file
View file

@ -0,0 +1,12 @@
import type { XRPC } from '@atcute/client';
import type { OAuthUserAgent } from '@atcute/oauth-browser-client';
export const userState = $state<{
rpc: XRPC | undefined;
agent: OAuthUserAgent | undefined;
did: string | undefined;
}>({
rpc: undefined,
agent: undefined,
did: undefined
});

View file

@ -1,6 +0,0 @@
import type { XRPC } from '@atcute/client';
import type { OAuthUserAgent } from '@atcute/oauth-browser-client';
import { writable, type Writable } from 'svelte/store';
export const rpc: Writable<XRPC | undefined> = writable(undefined);
export const agent: Writable<OAuthUserAgent | undefined> = writable(undefined);

View file

@ -7,6 +7,8 @@ import {
XrpcHandleResolver XrpcHandleResolver
} from '@atcute/identity-resolver'; } from '@atcute/identity-resolver';
import { configureOAuth } from '@atcute/oauth-browser-client';
import type { At, MeWoachFeedActivity } from '@atcute/client/lexicons'; import type { At, MeWoachFeedActivity } from '@atcute/client/lexicons';
const didDocumentResolver = new CompositeDidDocumentResolver({ const didDocumentResolver = new CompositeDidDocumentResolver({
@ -152,3 +154,11 @@ export async function getProgress(rpc: XRPC, did: string, uri: At.Uri) {
return 0; return 0;
} }
} }
export async function config() {
configureOAuth({
metadata: {
client_id: import.meta.env.VITE_OAUTH_CLIENT_ID,
redirect_uri: import.meta.env.VITE_OAUTH_REDIRECT_URI
}
});
}

View file

@ -1,15 +1,97 @@
<script lang="ts"> <script lang="ts">
import '../app.css'; import '../app.css';
let { children } = $props(); let { children } = $props();
import {
createAuthorizationUrl,
deleteStoredSession,
getSession,
OAuthUserAgent,
resolveFromIdentity
} from '@atcute/oauth-browser-client';
import { userState } from '$lib/state.svelte';
import { config } from '$lib/util';
import { onMount } from 'svelte';
async function login(handle: string) {
console.log('login', handle);
config();
const { identity, metadata } = await resolveFromIdentity(handle);
const authUrl = await createAuthorizationUrl({
metadata: metadata,
identity: identity,
scope: import.meta.env.VITE_OAUTH_SCOPE
});
window.location.assign(authUrl);
await new Promise((_resolve, reject) => {
const listener = () => {
reject(new Error(`user aborted the login request`));
};
window.addEventListener('pageshow', listener, { once: true });
});
}
async function logout() {
console.log('logout');
config();
try {
const session = await getSession(`did:${userState.did}`, { allowStale: true });
const agent = new OAuthUserAgent(session);
await agent.signOut();
} catch (err) {
deleteStoredSession(`did:${userState.did}`);
}
userState.rpc = undefined;
userState.agent = undefined;
userState.did = undefined;
}
onMount(async () => {
console.log('mounted');
config();
// if (userState.rpc == undefined) {
// console.log('userState.rpc is undefined, attempting to get session');
// try {
// const session = await getSession(`did:${userState.did}`, { allowStale: true });
// console.log('session', session);
// const agent = new OAuthUserAgent(session);
// const rpc = new XRPC({ handler: agent });
// userState.agent = agent;
// userState.rpc = rpc;
// const sessionInfo = await agent.getSession();
// userState.did = sessionInfo?.info.sub ?? '';
// } catch (err) {
// console.error('Error getting session:', err);
// }
// } else {
// console.log('userState.rpc is undefined');
// }
console.log(userState);
});
</script> </script>
<ul class="bg-gray-800 text-white p-4 flex space-x-4"> <ul class="flex space-x-4 bg-gray-800 p-4 text-white">
<li><a href="/" aria-label="home" class="icon-[mynaui--home] text-gray-300"></a></li> <li><a href="/" aria-label="home" class="icon-[mynaui--home] text-gray-300"></a></li>
<li><a href="/landing" aria-label="landing" class="icon-[mynaui--external-link] text-gray-300"></a></li> <li>
<a href="/landing" aria-label="landing" class="icon-[mynaui--external-link] text-gray-300"></a>
</li>
<li><a href="/search" aria-label="search" class="icon-[mynaui--search] text-gray-300"></a></li> <li><a href="/search" aria-label="search" class="icon-[mynaui--search] text-gray-300"></a></li>
<li><a href="/user/m.woach.me/" aria-label="user" class="icon-[mynaui--user] text-gray-300"></a></li> <li>
<a href="/user/m.woach.me/" aria-label="user" class="icon-[mynaui--user] text-gray-300"></a>
</li>
{#if userState.rpc}
<div>{userState.did}</div>
<button onclick={() => logout()}>logout</button>
{:else}
<button onclick={() => login('m.woach.me')}>login</button>
{/if}
</ul> </ul>
<div class="h-screen bg-gray-300 overflow-hidden"> <div class="h-screen overflow-hidden bg-gray-300">
{@render children()} {@render children()}
</div> </div>

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { agent, rpc } from '$lib/store'; import { userState } from '$lib/state.svelte';
import { config } from '$lib/util'; import { config } from '$lib/util';
import { XRPC } from '@atcute/client'; import { XRPC } from '@atcute/client';
import { OAuthUserAgent, finalizeAuthorization } from '@atcute/oauth-browser-client'; import { OAuthUserAgent, finalizeAuthorization } from '@atcute/oauth-browser-client';
@ -17,8 +17,10 @@
const agentItem = new OAuthUserAgent(session); const agentItem = new OAuthUserAgent(session);
const rpcItem = new XRPC({ handler: agentItem }); const rpcItem = new XRPC({ handler: agentItem });
rpc.set(rpcItem);
agent.set(agentItem); userState.did = (await agentItem?.getSession())?.info.sub ?? '';
userState.rpc = rpcItem;
userState.agent = agentItem;
goto('/'); goto('/');
}); });

View file

@ -1,2 +1,29 @@
<h1>Search</h1> <script lang="ts">
import { userState } from '$lib/state.svelte';
import { onMount } from 'svelte';
onMount(() => {
console.log('mounted');
console.log(userState);
if (userState.rpc !== undefined) {
(async () => {
try {
const response = await userState.rpc?.get('com.atproto.identity.resolveHandle', {
params: {
handle: 'mary.my.id'
}
});
if (response && 'data' in response) {
console.log('resolved handle', response.data);
} else {
console.error('Failed to resolve handle or data is undefined');
}
} catch (error) {
console.error('RPC request failed:', error);
}
})();
}
});
</script>
<h1>Search</h1>