Skip to content

Commit

Permalink
re-enable reactions
Browse files Browse the repository at this point in the history
  • Loading branch information
artlu99 committed Nov 4, 2024
1 parent 1b49c9c commit 0b76a10
Show file tree
Hide file tree
Showing 9 changed files with 713 additions and 57 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ REACT_APP_READ_TOKEN=XXXXXXXX-XXXX-XXXXX
REACT_APP_DEFAULT_FID=391262;
REACT_APP_NEYNAR_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
REACT_APP_PRIVY_APP_ID=xxxxxxxxxxxxxxxxxxxxxxxxx
REACT_APP_PRIVY_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxx
REACT_APP_PINATA_GATEWAY=https://gateway.pinata.cloud
REACT_APP_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
REACT_APP_PUBLIC_POSTHOG_KEY=xxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"devDependencies": {
"@cloudflare/workers-types": "^4.20240605.0",
"@farcaster/hub-nodejs": "^0.11.16",
"@rollup/plugin-inject": "^5.0.5",
"@tanstack/eslint-plugin-query": "^5.43.1",
"@types/country-list": "^2.1.4",
"@types/react": "^18.3.3",
Expand Down Expand Up @@ -105,6 +106,7 @@
"stylelint-processor-styled-components": "^1.10.0",
"typescript": "5.1.3",
"vite": "^5.2.12",
"vite-plugin-node-polyfills": "^0.22.0",
"vite-plugin-pwa": "^0.20.0",
"vite-plugin-svgr": "^4.2.0",
"webpack-bundle-analyzer": "^4.4.2",
Expand Down
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import jaJP from 'antd/lib/locale/ja_JP';
import GlobalStyle from './styles/GlobalStyle';

const appId = import.meta.env.REACT_APP_PRIVY_APP_ID;
const clientId = import.meta.env.REACT_APP_PRIVY_CLIENT_ID;

const App: React.FC = () => {
const { language } = useLanguage();
Expand Down Expand Up @@ -61,6 +62,7 @@ const App: React.FC = () => {
<GlobalStyle />
<PrivyProvider
appId={appId}
clientId={clientId}
config={{
loginMethods: ['farcaster'],
embeddedWallets: { createOnLogin: 'users-without-wallets' },
Expand Down
1 change: 0 additions & 1 deletion src/api/reactionOnHash.api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { httpApi } from '@app/api/http.api';

interface ReactionRequest {
privyAuthToken: string;
target: { fid: number; hash: string };
reactionType: 'like' | 'recast' | 'unlike' | 'unrecast';
}
Expand Down
12 changes: 8 additions & 4 deletions src/components/apps/cast/Cast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,14 @@ export const Cast: React.FC<CastProps> = ({
description
)}
{sassyHash?.isDecrypted ? (
<div id="sassy-hash-text" className="text-xl">
<div id="sassy-hash-text" key={`${castHash}-sassy-hash-text`} className="text-xl">
{showThisSassyCast
? sassyHash.decodedText
: [<a onClick={() => setShowThisSassyCast(true)}>[Sassy Reveal]</a>]}
: [
<a onClick={() => setShowThisSassyCast(true)} key={`${castHash}-sassy-reveal`}>
[Sassy Reveal]
</a>,
]}
</div>
) : null}
</S.Description>
Expand All @@ -160,7 +164,7 @@ export const Cast: React.FC<CastProps> = ({
<BaseDivider />
<S.InfoWrapper>
<Reactions
castHash={castHash}
target={{ fid, hash: castHash }}
replies={replies}
recasts={recasts}
likes={likes}
Expand All @@ -176,7 +180,7 @@ export const Cast: React.FC<CastProps> = ({
<S.TagsWrapper>
{tags.map((tag) =>
linkTo ? (
<Link to={`/~/channel/${linkTo}`}>
<Link to={`/~/channel/${linkTo}`} key={`${castHash}-${tag.title}-${tag.bgColor}`}>
<BaseHashTag key={`${castHash}-${tag.title}-${tag.bgColor}`} title={tag.title} bgColor={tag.bgColor} />
</Link>
) : (
Expand Down
60 changes: 26 additions & 34 deletions src/components/apps/cast/Reactions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { HubReactionType, HubReactionsResponse, HubReactionsStreamItem } from '@app/api/hubble-http-types';
import { setReactionOnHash } from '@app/api/reactionOnHash.api';
import { HubReactionsResponse, HubReactionsStreamItem, HubReactionType } from '@app/api/hubble-http-types';
import { getFidWithFallback } from '@app/auth/fids';
import { ReactionsAnalytics } from '@app/components/apps/cast/ReactionsAnalytics';
import { BaseBadge } from '@app/components/common/BaseBadge/BaseBadge';
Expand All @@ -8,13 +7,14 @@ import { useAppSelector } from '@app/hooks/reduxHooks';
import { useResponsive } from '@app/hooks/useResponsive';
import { hubReactionsByFidQuery } from '@app/queries/queries';
import { BASE_COLORS } from '@app/styles/themes/constants';
import { usePrivy } from '@privy-io/react-auth';
import { useFarcasterSigner, usePrivy } from '@privy-io/react-auth';
import { ExternalEd25519Signer, HubRestAPIClient } from '@standard-crypto/farcaster-js';
import { useQuery } from '@tanstack/react-query';
import { BarChartBigIcon, LucideHeart, LucideMessageSquare, LucideRepeat2 } from 'lucide-react';
import { Dispatch, SetStateAction, useMemo, useState } from 'react';
import * as S from './Cast.styles';

const TEMP_DISABLE_REACTIONS = true;
const hubUrl = 'https://hub.farcaster.standardcrypto.vc:2281';

const hubReactionsToStreamItems = (reactions: HubReactionsResponse | undefined): HubReactionsStreamItem[] => {
return (reactions?.messages ?? []).map((m) => {
Expand All @@ -35,7 +35,7 @@ const isStateAdded = (stream: HubReactionsStreamItem[], hash: string): boolean =
};

export interface ReactionsProps {
castHash: string;
target: { fid: number; hash: string };
replies: number;
recasts: number;
likes: number;
Expand All @@ -46,7 +46,7 @@ export interface ReactionsProps {
}

export const Reactions: React.FC<ReactionsProps> = ({
castHash,
target,
replies,
recasts,
likes,
Expand All @@ -71,10 +71,14 @@ export const Reactions: React.FC<ReactionsProps> = ({
const reactionBarMarginSize = isDesktop ? 60 : isTablet ? 40 : isLandscapeMobile ? 50 : 10;
const reactionIconSize = isDesktop ? 18 : isTablet ? 24 : 24;

const { user: privyUser, getAccessToken } = usePrivy();
const { authenticated, user: privyUser } = usePrivy();
const user = privyUser ? privyUser.farcaster : null;
const fid = getFidWithFallback(privyUser);

const { getFarcasterSignerPublicKey, signFarcasterMessage } = useFarcasterSigner();
const client = new HubRestAPIClient({ hubUrl });
const privySigner = new ExternalEd25519Signer(signFarcasterMessage, getFarcasterSignerPublicKey);

const flQuery = useQuery(hubReactionsByFidQuery(fid, HubReactionType.LIKE));
const memodLikes = useMemo(() => {
if (flQuery.isLoading || flQuery.error) return null;
Expand All @@ -87,46 +91,34 @@ export const Reactions: React.FC<ReactionsProps> = ({
return hubReactionsToStreamItems(frQuery?.data);
}, [frQuery]);

const handleLike = async (castHash: string) => {
const privyAuthToken = await getAccessToken();
if (!!user?.fid && !!user?.signerPublicKey && privyAuthToken) {
// TODO: reactions via Hubble
if (TEMP_DISABLE_REACTIONS) return;

if (isStateAdded(memodLikes ?? [], castHash) || allLikooors.includes(user?.fid ?? -1)) {
const handleLike = async (target: { fid: number; hash: string }) => {
if (authenticated && !!user?.fid && !!user?.signerPublicKey) {
if (isStateAdded(memodLikes ?? [], target.hash) || allLikooors.includes(user?.fid ?? -1)) {
setOptimisticLikes(0);
await setReactionOnHash({ privyAuthToken, target: { fid: user.fid, hash: castHash }, reactionType: 'unlike' });
await client.removeReaction({ type: 'like', target }, user.fid, privySigner);
} else {
setOptimisticLikes(1);
await setReactionOnHash({ privyAuthToken, target: { fid: user.fid, hash: castHash }, reactionType: 'like' });
await client.submitReaction({ type: 'like', target }, user.fid, privySigner);
}
}
};

const handleRecast = async (castHash: string) => {
const privyAuthToken = await getAccessToken();
if (!!user?.fid && !!user?.signerPublicKey && privyAuthToken) {
// TODO: reactions via Hubble
if (TEMP_DISABLE_REACTIONS) return;

if (isStateAdded(memodRecasts ?? [], castHash) || allRecastooors.includes(user?.fid ?? -1)) {
const handleRecast = async (target: { fid: number; hash: string }) => {
if (authenticated && !!user?.fid && !!user?.signerPublicKey) {
if (isStateAdded(memodRecasts ?? [], target.hash) || allRecastooors.includes(user?.fid ?? -1)) {
setOptimisticRecasts(0);
await setReactionOnHash({
privyAuthToken,
target: { fid: user.fid, hash: castHash },
reactionType: 'unrecast',
});
await client.removeReaction({ type: 'recast', target }, user.fid, privySigner);
} else {
setOptimisticRecasts(1);
await setReactionOnHash({ privyAuthToken, target: { fid: user.fid, hash: castHash }, reactionType: 'recast' });
await client.submitReaction({ type: 'recast', target }, user.fid, privySigner);
}
}
};

const amLikooor =
isStateAdded(memodLikes ?? [], castHash) || optimisticLikes || allLikooors.includes(user?.fid ?? -1);
isStateAdded(memodLikes ?? [], target.hash) || optimisticLikes || allLikooors.includes(user?.fid ?? -1);
const amRecastooor =
isStateAdded(memodRecasts ?? [], castHash) || optimisticRecasts || allRecastooors.includes(user?.fid ?? -1);
isStateAdded(memodRecasts ?? [], target.hash) || optimisticRecasts || allRecastooors.includes(user?.fid ?? -1);

return showReactions ? (
<>
Expand All @@ -136,19 +128,19 @@ export const Reactions: React.FC<ReactionsProps> = ({
</BaseBadge>
<BaseDivider type="vertical" style={{ marginLeft: reactionBarMarginSize }} />
<BaseBadge count={recasts + optimisticRecasts} color={amRecastooor ? highlightedColor : shadedColor}>
<LucideRepeat2 size={reactionIconSize} onClick={() => handleRecast(castHash)} />
<LucideRepeat2 size={reactionIconSize} onClick={() => handleRecast(target)} />
</BaseBadge>
<BaseDivider type="vertical" style={{ marginLeft: reactionBarMarginSize }} />
<BaseBadge count={likes + optimisticLikes} color={amLikooor ? highlightedColor : shadedColor}>
<LucideHeart size={reactionIconSize} onClick={() => handleLike(castHash)} />
<LucideHeart size={reactionIconSize} onClick={() => handleLike(target)} />
</BaseBadge>
<BaseDivider type="vertical" style={{ marginLeft: reactionBarMarginSize }} />
<BarChartBigIcon size={reactionIconSize * 1.2} onClick={() => setAnalyticsOpen(!isAnalyticsOpen)} />
<BaseDivider type="vertical" style={{ marginLeft: reactionBarMarginSize }} />
</S.Description>
{isAnalyticsOpen && (
<ReactionsAnalytics
castHash={castHash}
castHash={target.hash}
recasts={recasts}
likes={likes}
allLikooors={allLikooors}
Expand Down
2 changes: 1 addition & 1 deletion src/components/layouts/main/sider/MainSider/MainSider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const MainSider: React.FC<MainSiderProps> = ({ isCollapsed, setCollapsed, ...pro
<SiderMenu setCollapsed={setCollapsed} />
</S.SiderContent>
</S.Sider>
{mobileOnly && <Overlay onClick={toggleSider} show={!!!isCollapsed} />}
{mobileOnly && <Overlay onClick={toggleSider} show={!isCollapsed} />}
</>
);
};
Expand Down
10 changes: 8 additions & 2 deletions vite.config.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import inject from '@rollup/plugin-inject';
import react from '@vitejs/plugin-react';
import path from 'path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import { VitePWA } from 'vite-plugin-pwa';
import svgr from 'vite-plugin-svgr';

export default defineConfig(() => {
return {
base: 'https://client-bcbhshow.artlu.xyz',
envPrefix: 'REACT_APP_',
build: {
outDir: 'build',
rollupOptions: {
plugins: [inject({ Buffer: ['buffer/', 'Buffer'] })],
},
},
plugins: [
nodePolyfills(),
react(),
// svgr options: https://react-svgr.com/docs/options/
svgr({ svgrOptions: { icon: true } }),
Expand Down
Loading

0 comments on commit 0b76a10

Please sign in to comment.