diff --git a/apps/events/package.json b/apps/events/package.json index 92f219be..1fbe281a 100644 --- a/apps/events/package.json +++ b/apps/events/package.json @@ -20,6 +20,7 @@ "@automerge/automerge": "^v2.2.9-alpha.3", "@automerge/automerge-repo": "^2.0.0-alpha.14", "@automerge/automerge-repo-react-hooks": "^2.0.0-alpha.14", + "@graphprotocol/graph-framework": "workspace:*", "@noble/hashes": "^1.5.0", "@privy-io/react-auth": "^1.88.4", "@radix-ui/react-avatar": "^1.1.1", @@ -28,12 +29,10 @@ "@tanstack/react-router": "^1.62.1", "@xmtp/react-sdk": "^9.0.0", "@xmtp/xmtp-js": "^13.0.0", - "@xstate/store": "^2.6.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "effect": "^3.10.19", "ethers": "^6.13.3", - "@graphprotocol/graph-framework": "workspace:*", "isomorphic-ws": "^5.0.0", "lucide-react": "^0.441.0", "react": "^18.3.1", diff --git a/apps/events/src/routes/playground.tsx b/apps/events/src/routes/playground.tsx index 6f71d3f5..ded51d7c 100644 --- a/apps/events/src/routes/playground.tsx +++ b/apps/events/src/routes/playground.tsx @@ -1,9 +1,8 @@ import { RepoContext } from '@automerge/automerge-repo-react-hooks'; import { createFileRoute } from '@tanstack/react-router'; -import { useSelector } from '@xstate/store/react'; import { useState } from 'react'; -import { GraphFramework, store, useGraphFramework } from '@graphprotocol/graph-framework'; +import { GraphFramework, store, useGraphFramework, useSelector } from '@graphprotocol/graph-framework'; import { AutomergeApp } from '@/components/automerge-app'; import { DebugInvitations } from '@/components/debug-invitations'; diff --git a/apps/events/tailwind.config.js b/apps/events/tailwind.config.js index 550bd074..a7f1c57a 100644 --- a/apps/events/tailwind.config.js +++ b/apps/events/tailwind.config.js @@ -1,3 +1,5 @@ +import tailwindcssAnimate from 'tailwindcss-animate'; + /** @type {import('tailwindcss').Config} */ export default { darkMode: ['class'], @@ -53,5 +55,5 @@ export default { }, }, }, - plugins: [require('tailwindcss-animate')], + plugins: [tailwindcssAnimate], }; diff --git a/packages/graph-framework/src/core.tsx b/packages/graph-framework/src/core.tsx index 5fb02a23..10d65650 100644 --- a/packages/graph-framework/src/core.tsx +++ b/packages/graph-framework/src/core.tsx @@ -2,6 +2,7 @@ import * as automerge from '@automerge/automerge'; import { uuid } from '@automerge/automerge'; import { type AutomergeUrl, type DocHandle, Repo } from '@automerge/automerge-repo'; import { bytesToHex, hexToBytes } from '@noble/hashes/utils'; +import { useSelector as useSelectorStore } from '@xstate/store/react'; import { Effect, Exit } from 'effect'; import * as Schema from 'effect/Schema'; import { createContext, useContext, useEffect, useState } from 'react'; @@ -23,7 +24,6 @@ import type { SpaceEvent, SpaceState } from '@graph-framework/space-events'; import { acceptInvitation, applyEvent, createInvitation, createSpace } from '@graph-framework/space-events'; import { generateId } from '@graph-framework/utils'; -import { useSelector } from '@xstate/store/react'; import { assertExhaustive } from './assertExhaustive.js'; import type { SpaceStorageEntry } from './store.js'; import { store } from './store.js'; @@ -82,11 +82,9 @@ const GraphFrameworkContext = createContext<{ export function GraphFramework({ children, accountId }: Props) { const [websocketConnection, setWebsocketConnection] = useState(); const [repo] = useState(() => new Repo({})); - const [invitations, setInvitations] = useState([]); const [automergeHandle] = useState>(() => repo.find(hardcodedUrl)); - const storeState = useSelector(store, (state) => state.context); - const spaces = storeState.spaces; - + const spaces = useSelectorStore(store, (state) => state.context.spaces); + const invitations = useSelectorStore(store, (state) => state.context.invitations); // Create a stable WebSocket connection that only depends on accountId useEffect(() => { const websocketConnection = new WebSocket(`ws://localhost:3030/?accountId=${accountId}`); @@ -266,7 +264,10 @@ export function GraphFramework({ children, accountId }: Props) { break; } case 'list-invitations': { - setInvitations(response.invitations.map((invitation) => invitation)); + store.send({ + type: 'setInvitations', + invitations: response.invitations.map((invitation) => invitation), + }); break; } case 'update-confirmed': { @@ -499,3 +500,5 @@ export function GraphFramework({ children, accountId }: Props) { export const useGraphFramework = () => { return useContext(GraphFrameworkContext); }; + +export const useSelector = useSelectorStore; diff --git a/packages/graph-framework/src/store.ts b/packages/graph-framework/src/store.ts index 83286f8e..c6c2dc62 100644 --- a/packages/graph-framework/src/store.ts +++ b/packages/graph-framework/src/store.ts @@ -1,4 +1,4 @@ -import type { Updates } from '@graph-framework/messages'; +import type { Invitation, Updates } from '@graph-framework/messages'; import type { SpaceEvent, SpaceState } from '@graph-framework/space-events'; import { createStore } from '@xstate/store'; @@ -15,6 +15,7 @@ export type SpaceStorageEntry = { interface StoreContext { spaces: SpaceStorageEntry[]; updatesInFlight: string[]; + invitations: Invitation[]; encryptionPrivateKey: string; automergeDocumentId: string; } @@ -22,6 +23,7 @@ interface StoreContext { const initialStoreContext: StoreContext = { spaces: [], updatesInFlight: [], + invitations: [], encryptionPrivateKey: '', automergeDocumentId: '', }; @@ -29,6 +31,12 @@ const initialStoreContext: StoreContext = { export const store = createStore({ context: initialStoreContext, on: { + setInvitations: (context, event: { invitations: Invitation[] }) => { + return { + ...context, + invitations: event.invitations, + }; + }, setAutomergeDocumentId: (context, event: { automergeDocumentId: string }) => { return { ...context, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8909aa99..b15e9081 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,9 +68,6 @@ importers: '@xmtp/xmtp-js': specifier: ^13.0.0 version: 13.0.3(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) - '@xstate/store': - specifier: ^2.6.1 - version: 2.6.1(react@18.3.1) class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -5285,7 +5282,7 @@ snapshots: '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -5471,7 +5468,7 @@ snapshots: '@babel/parser': 7.26.2 '@babel/template': 7.25.9 '@babel/types': 7.26.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6087,7 +6084,7 @@ snapshots: '@metamask/utils@3.6.0': dependencies: '@types/debug': 4.1.12 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7 semver: 7.6.3 superstruct: 1.0.4 transitivePeerDependencies: @@ -6097,7 +6094,7 @@ snapshots: dependencies: '@ethereumjs/tx': 4.2.0 '@types/debug': 4.1.12 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7 semver: 7.6.3 superstruct: 1.0.4 transitivePeerDependencies: