Skip to content

Commit

Permalink
feat: simple lens<>xmtp web integration (#401)
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysu authored Aug 7, 2023
1 parent fb7a76f commit fc31f14
Show file tree
Hide file tree
Showing 50 changed files with 1,409 additions and 114 deletions.
8 changes: 8 additions & 0 deletions .changeset/thin-carpets-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@lens-protocol/shared-kernel": minor
"@lens-protocol/react-web": minor
"@lens-protocol/domain": minor
"@lens-protocol/react": minor
---

**Added** experimental hooks that integrate with @xmtp/react-sdk
1 change: 1 addition & 0 deletions examples/web-wagmi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@ethersproject/providers": "^5.7.2",
"@lens-protocol/react-web": "workspace:*",
"@lens-protocol/wagmi": "workspace:*",
"@xmtp/react-sdk": "1.0.0-preview.40",
"example-shared": "workspace:*",
"react": "^18.2.0",
"react-cool-inview": "^3.0.1",
Expand Down
204 changes: 112 additions & 92 deletions examples/web-wagmi/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
development,
} from '@lens-protocol/react-web';
import { bindings as wagmiBindings } from '@lens-protocol/wagmi';
import { XMTPProvider } from '@xmtp/react-sdk';
import toast, { Toaster } from 'react-hot-toast';
import { Route, BrowserRouter as Router, Routes } from 'react-router-dom';
import { WagmiConfig, configureChains, createConfig } from 'wagmi';
Expand All @@ -26,6 +27,10 @@ import { UseExplorePublications } from './discovery/UseExplorePublications';
import { UseFeed } from './discovery/UseFeed';
import { UseSearchProfiles } from './discovery/UseSearchProfiles';
import { UseSearchPublications } from './discovery/UseSearchPublications';
import { InboxPage } from './inbox/InboxPage';
import { UseConversation } from './inbox/UseConversation';
import { UseConversations } from './inbox/UseConversations';
import { UseCreateConversation } from './inbox/UseCreateConversation';
import { MiscPage } from './misc/MiscPage';
import { Polls } from './misc/Polls';
import { UseApproveModule } from './misc/UseApproveModule';
Expand Down Expand Up @@ -112,104 +117,119 @@ export function App() {
return (
<WagmiConfig config={config}>
<LensProvider config={lensConfig} onError={notifyError} onLogout={notifyLogout}>
<Router>
<Header />
<main>
<Breadcrumbs />
<GenericErrorBoundary fallback={ErrorMessage}>
<Routes>
<Route index element={<Home />} />
<XMTPProvider>
<Router>
<Header />
<main>
<Breadcrumbs />
<GenericErrorBoundary fallback={ErrorMessage}>
<Routes>
<Route index element={<Home />} />

<Route path="/authentication">
<Route index element={<AuthenticationPage />} />
<Route path="loginSpecificProfile" element={<LoginSpecificProfile />} />
</Route>
<Route path="/authentication">
<Route index element={<AuthenticationPage />} />
<Route path="loginSpecificProfile" element={<LoginSpecificProfile />} />
</Route>

<Route path="/publications">
<Route index element={<PublicationsPage />} />
<Route path="usePublication" element={<UsePublication />} />
<Route path="usePublications" element={<UsePublications />} />
<Route path="useComments" element={<UsePublication />} />
<Route path="useCollectedPublications" element={<UseCollectedPublications />} />
<Route path="useCreatePost" element={<UseCreatePost />} />
<Route path="useCreateEncryptedPost" element={<UseCreateEncryptedPost />} />
<Route path="useCreateComment" element={<UseCreateComment />} />
<Route
path="useProfilePublicationsForSale"
element={<UseProfilePublicationsForSale />}
/>
<Route path="useReaction" element={<UseReaction />} />
<Route path="useWhoReacted" element={<UseWhoReacted />} />
<Route path="useReportPublication" element={<UseReportPublication />} />
<Route path="useHidePublication" element={<UseHidePublication />} />
<Route
path="useWhoCollectedPublication"
element={<UseWhoCollectedPublication />}
/>
<Route path="UseCreateMirror" element={<UseCreateMirror />} />
<Route path="useWhoMirroredPublication" element={<UseWhoMirroredPublication />} />
<Route path="useCollect" element={<UseCollect />} />
<Route path="useNotInterested" element={<UseNotInterested />} />
<Route path="useMyBookmarks" element={<UseMyBookmarks />} />
<Route path="useBookmarkToggle" element={<UseBookmarkToggle />} />
</Route>
<Route path="/publications">
<Route index element={<PublicationsPage />} />
<Route path="usePublication" element={<UsePublication />} />
<Route path="usePublications" element={<UsePublications />} />
<Route path="useComments" element={<UsePublication />} />
<Route path="useCollectedPublications" element={<UseCollectedPublications />} />
<Route path="useCreatePost" element={<UseCreatePost />} />
<Route path="useCreateEncryptedPost" element={<UseCreateEncryptedPost />} />
<Route path="useCreateComment" element={<UseCreateComment />} />
<Route
path="useProfilePublicationsForSale"
element={<UseProfilePublicationsForSale />}
/>
<Route path="useReaction" element={<UseReaction />} />
<Route path="useWhoReacted" element={<UseWhoReacted />} />
<Route path="useReportPublication" element={<UseReportPublication />} />
<Route path="useHidePublication" element={<UseHidePublication />} />
<Route
path="useWhoCollectedPublication"
element={<UseWhoCollectedPublication />}
/>
<Route path="UseCreateMirror" element={<UseCreateMirror />} />
<Route
path="useWhoMirroredPublication"
element={<UseWhoMirroredPublication />}
/>
<Route path="useCollect" element={<UseCollect />} />
<Route path="useNotInterested" element={<UseNotInterested />} />
<Route path="useMyBookmarks" element={<UseMyBookmarks />} />
<Route path="useBookmarkToggle" element={<UseBookmarkToggle />} />
</Route>

<Route path="/profiles">
<Route index element={<ProfilesPage />} />
<Route path="useCreateProfile" element={<UseCreateProfile />} />
<Route path="useProfile" element={<UseProfile />} />
<Route path="useProfiles" element={<UseProfiles />} />
<Route path="useUpdateDispatcherConfig" element={<UseUpdateDispatcherConfig />} />
<Route path="useMutualFollowers" element={<UseMutualFollowers />} />
<Route path="useProfilesToFollow" element={<ProfilesToFollow />} />
<Route path="useFollow" element={<UseFollowAndUnfollow />} />
<Route path="useUpdateProfileImage" element={<UseUpdateProfileImage />} />
<Route path="useUpdateFollowPolicy" element={<UseUpdateFollowPolicy />} />
<Route path="useUpdateProfileDetails" element={<UseUpdateProfileDetails />} />
<Route path="useActiveProfileSwitch" element={<UseActiveProfileSwitch />} />
<Route path="useProfilesOwnedBy" element={<UseProfilesOwnedBy />} />
<Route path="useProfileFollowers" element={<UseProfileFollowers />} />
<Route path="useProfileFollowing" element={<UseProfileFollowing />} />
<Route path="useProfileGuardian" element={<UseProfileGuardian />} />
</Route>
<Route path="/profiles">
<Route index element={<ProfilesPage />} />
<Route path="useCreateProfile" element={<UseCreateProfile />} />
<Route path="useProfile" element={<UseProfile />} />
<Route path="useProfiles" element={<UseProfiles />} />
<Route
path="useUpdateDispatcherConfig"
element={<UseUpdateDispatcherConfig />}
/>
<Route path="useMutualFollowers" element={<UseMutualFollowers />} />
<Route path="useProfilesToFollow" element={<ProfilesToFollow />} />
<Route path="useFollow" element={<UseFollowAndUnfollow />} />
<Route path="useUpdateProfileImage" element={<UseUpdateProfileImage />} />
<Route path="useUpdateFollowPolicy" element={<UseUpdateFollowPolicy />} />
<Route path="useUpdateProfileDetails" element={<UseUpdateProfileDetails />} />
<Route path="useActiveProfileSwitch" element={<UseActiveProfileSwitch />} />
<Route path="useProfilesOwnedBy" element={<UseProfilesOwnedBy />} />
<Route path="useProfileFollowers" element={<UseProfileFollowers />} />
<Route path="useProfileFollowing" element={<UseProfileFollowing />} />
<Route path="useProfileGuardian" element={<UseProfileGuardian />} />
</Route>

<Route path="/discovery">
<Route index element={<DiscoveryPage />} />
<Route path="useFeed" element={<UseFeed />} />
<Route path="useExploreProfiles" element={<UseExploreProfiles />} />
<Route path="useExplorePublications" element={<UseExplorePublications />} />
<Route path="useSearchProfiles" element={<UseSearchProfiles />} />
<Route path="useSearchPublications" element={<UseSearchPublications />} />
</Route>
<Route path="/discovery">
<Route index element={<DiscoveryPage />} />
<Route path="useFeed" element={<UseFeed />} />
<Route path="useExploreProfiles" element={<UseExploreProfiles />} />
<Route path="useExplorePublications" element={<UseExplorePublications />} />
<Route path="useSearchProfiles" element={<UseSearchProfiles />} />
<Route path="useSearchPublications" element={<UseSearchPublications />} />
</Route>

<Route path="/revenue">
<Route index element={<RevenuePage />} />
<Route path="usePublicationRevenue" element={<UsePublicationRevenue />} />
<Route path="useProfileFollowRevenue" element={<UseProfileFollowRevenue />} />
<Route
path="useProfilePublicationRevenue"
element={<UseProfilePublicationRevenue />}
/>
</Route>
<Route path="/revenue">
<Route index element={<RevenuePage />} />
<Route path="usePublicationRevenue" element={<UsePublicationRevenue />} />
<Route path="useProfileFollowRevenue" element={<UseProfileFollowRevenue />} />
<Route
path="useProfilePublicationRevenue"
element={<UseProfilePublicationRevenue />}
/>
</Route>

<Route path="/misc">
<Route index element={<MiscPage />} />
<Route path="/misc/useCurrencies" element={<UseCurrencies />} />
<Route path="/misc/useEnabledModules" element={<UseEnabledModules />} />
<Route path="/misc/useNotifications" element={<UseNotifications />} />
<Route
path="/misc/useUnreadNotificationCount"
element={<UseUnreadNotificationCount />}
/>
<Route path="/misc/useApproveModule" element={<UseApproveModule />} />
<Route path="/misc/useRecentTransactions" element={<UseRecentTransactions />} />
<Route path="/misc/polls" element={<Polls />} />
</Route>
</Routes>
</GenericErrorBoundary>
<Toaster />
</main>
</Router>
<Route path="/misc">
<Route index element={<MiscPage />} />
<Route path="useCurrencies" element={<UseCurrencies />} />
<Route path="useEnabledModules" element={<UseEnabledModules />} />
<Route path="useNotifications" element={<UseNotifications />} />
<Route
path="useUnreadNotificationCount"
element={<UseUnreadNotificationCount />}
/>
<Route path="useApproveModule" element={<UseApproveModule />} />
<Route path="useRecentTransactions" element={<UseRecentTransactions />} />
<Route path="polls" element={<Polls />} />
</Route>

<Route path="/inbox">
<Route index element={<InboxPage />} />
<Route path="useConversations" element={<UseConversations />} />
<Route path="useConversations/:conversationId" element={<UseConversation />} />
<Route path="useCreateConversation" element={<UseCreateConversation />} />
</Route>
</Routes>
</GenericErrorBoundary>
<Toaster />
</main>
</Router>
</XMTPProvider>
</LensProvider>
</WagmiConfig>
);
Expand Down
3 changes: 3 additions & 0 deletions examples/web-wagmi/src/components/auth/LogoutButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { useWalletLogout } from '@lens-protocol/react-web';
import { useClient } from '@xmtp/react-sdk';
import { useDisconnect } from 'wagmi';

export function LogoutButton() {
const { execute: logout, isPending: isLogoutPending } = useWalletLogout();
const { disconnect: disconnectXmtp } = useClient();

const { disconnectAsync } = useDisconnect();

const onLogoutClick = async () => {
disconnectXmtp();
await logout();
await disconnectAsync();
};
Expand Down
4 changes: 4 additions & 0 deletions examples/web-wagmi/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ export const CATEGORIES = [
label: 'Misc',
path: '/misc',
},
{
label: 'Inbox',
path: '/inbox',
},
];
26 changes: 26 additions & 0 deletions examples/web-wagmi/src/inbox/InboxPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { LinkCard } from '../components/LinkCard';

const inboxHooks = [
{
label: 'useConversations',
description: `List all conversations. Show a conversation with messages. Send a message.`,
path: '/inbox/useConversations',
},
{
label: 'useCreateConversation',
description: `Start a new conversation.`,
path: '/inbox/useCreateConversation',
},
];

export function InboxPage() {
return (
<div>
<h1>Inbox</h1>

{inboxHooks.map((link) => (
<LinkCard key={link.path} {...link} />
))}
</div>
);
}
88 changes: 88 additions & 0 deletions examples/web-wagmi/src/inbox/UseConversation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { ProfileOwnedByMe, useEnhanceConversation } from '@lens-protocol/react-web';
import { Conversation, useClient, useConversations } from '@xmtp/react-sdk';
import { useParams } from 'react-router-dom';

import { LoginButton, WhenLoggedInWithProfile, WhenLoggedOut } from '../components/auth';
import { Loading } from '../components/loading/Loading';
import { ConversationCard } from './components/ConversationCard';
import { EnableConversationsButton } from './components/EnableConversationsButton';
import { MessageComposer } from './components/MessageComposer';
import { MessagesCard } from './components/MessagesCard';

type UseConversationsInnerProps = {
conversation: Conversation;
profile: ProfileOwnedByMe;
};

function UseConversationInner({ conversation, profile }: UseConversationsInnerProps) {
const { data: enhancedConversation, loading } = useEnhanceConversation({ conversation, profile });

if (loading) return <Loading />;

if (enhancedConversation) {
return (
<div>
<ConversationCard conversation={enhancedConversation} />
<MessageComposer conversation={enhancedConversation} />
<MessagesCard conversation={enhancedConversation} />
</div>
);
}

return <div>Conversation not found</div>;
}

type EnableConversationsProps = {
profile: ProfileOwnedByMe;
conversationId: string;
};

function EnableConversations({ profile, conversationId }: EnableConversationsProps) {
const { client } = useClient();
const { conversations, error, isLoading } = useConversations();

if (!client) {
return <EnableConversationsButton />;
}

if (error) {
return <div>An error occurred while fetching conversations</div>;
}

const requestedConversation = conversations?.find((c) => c.topic === conversationId);

return (
<div>
{isLoading && <Loading />}

{requestedConversation && (
<UseConversationInner conversation={requestedConversation} profile={profile} />
)}
</div>
);
}

export function UseConversation() {
const { conversationId } = useParams();

if (!conversationId) {
return <div>ConversationId not provided</div>;
}

return (
<>
<h1>
<code>useConversation</code>
</h1>
<WhenLoggedInWithProfile>
{({ profile }) => <EnableConversations profile={profile} conversationId={conversationId} />}
</WhenLoggedInWithProfile>
<WhenLoggedOut>
<div>
<p>You must be logged in to use this example.</p>
<LoginButton />
</div>
</WhenLoggedOut>
</>
);
}
Loading

0 comments on commit fc31f14

Please sign in to comment.