Skip to content

Commit

Permalink
add embeds
Browse files Browse the repository at this point in the history
  • Loading branch information
hellno committed Sep 25, 2023
1 parent 9592914 commit a6ddd8a
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 20 deletions.
59 changes: 45 additions & 14 deletions src/common/components/CastRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import HotkeyTooltipWrapper from './HotkeyTooltipWrapper';
import get from 'lodash.get';
import Linkify from "linkify-react";
import { isImageUrl } from '../helpers/text';
import OnchainEmbed from './Embeds/OnchainEmbed';
import WarpcastEmbed from './Embeds/WarpcastEmbed';

interface CastRowProps {
cast: CastType;
channels: ChannelType[];
showChannel?: boolean;
onSelect?: () => void;
isSelected?: boolean;
Expand All @@ -45,18 +46,24 @@ const renderLink = ({ attributes, content }) => {
};


export const CastRow = ({ cast, isSelected, showChannel, onSelect, channels, isThreadView = false }: CastRowProps) => {
export const CastRow = ({ cast, isSelected, showChannel, onSelect, isThreadView = false }: CastRowProps) => {
// if (isSelected) console.log(cast);

const { accounts, selectedAccountIdx } = useAccountStore();
const {
accounts,
selectedAccountIdx,
allChannels: channels,
} = useAccountStore();

const [didLike, setDidLike] = useState(false)
const [didRecast, setDidRecast] = useState(false)

const selectedAccount = accounts[selectedAccountIdx];
const userFid = Number(selectedAccount.platformAccountId);
const authorFid = cast.author.fid;

const embedUrl = cast.embeds.length > 0 ? cast.embeds[0].url : null;
const hasEmbeds = cast.embeds.length > 0;
const embedUrl = hasEmbeds ? cast.embeds[0].url : null;
const embedImageUrl = embedUrl && isImageUrl(embedUrl) ? embedUrl : null;
const now = new Date();

Expand All @@ -75,17 +82,25 @@ export const CastRow = ({ cast, isSelected, showChannel, onSelect, channels, isT
}
const reactions = getCastReactionsObj();

useHotkeys('l', () => {
if (isSelected) {
onClickReaction(CastReactionType.likes, reactions[CastReactionType.likes].isActive)
}
}, { enabled: isSelected }, [isSelected, selectedAccountIdx, authorFid, cast.hash, reactions.likes]);
useHotkeys('l',
() => {
if (isSelected) {
onClickReaction(CastReactionType.likes, reactions[CastReactionType.likes].isActive)
}
},
{ enabled: isSelected },
[isSelected, selectedAccountIdx, authorFid, cast.hash, reactions.likes]
);

useHotkeys('shift+r', () => {
if (isSelected) {
onClickReaction(CastReactionType.recasts, reactions[CastReactionType.recasts].isActive)
}
}, { enabled: isSelected }, [isSelected, selectedAccountIdx, authorFid, cast.hash, reactions.recasts]);
useHotkeys('shift+r',
() => {
if (isSelected) {
onClickReaction(CastReactionType.recasts, reactions[CastReactionType.recasts].isActive)
}
},
{ enabled: isSelected },
[isSelected, selectedAccountIdx, authorFid, cast.hash, reactions.recasts]
);

const getChannelForParentUrl = (parentUrl: string | null): ChannelType | undefined => parentUrl ?
channels.find((channel) => channel.url === parentUrl) : undefined;
Expand Down Expand Up @@ -184,6 +199,21 @@ export const CastRow = ({ cast, isSelected, showChannel, onSelect, channels, isT
</Linkify>
)

// this can be images, open-graph links
// in future: twitter, youtube videos, spotify embeds, etc
const renderEmbeds = () => (
<div className="mt-4">
{map(cast.embeds, (embed) => {
if (embed.url.startsWith('"chain:')) {
return <OnchainEmbed url={embed.url} />
} else if (embed.url.startsWith('https://warpcast.com')) {
return <WarpcastEmbed url={embed.url} />
} else {
return null;
}
})}
</div>);

const channel = showChannel ? getChannelForParentUrl(cast.parent_url) : null;

const authorPfpUrl = cast.author.pfp_url || cast.author.pfp?.url;
Expand Down Expand Up @@ -232,6 +262,7 @@ export const CastRow = ({ cast, isSelected, showChannel, onSelect, channels, isT
{embedImageUrl && <ImgurImage url={embedImageUrl} />}
</div>
{renderCastReactions(cast)}
{renderEmbeds()}
</div>
</div>
</div>
Expand Down
2 changes: 0 additions & 2 deletions src/common/components/CastThreadView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const CastThreadView = ({ cast, onBack, fid, isActive }: CastThreadViewPr
const draftIdx = useNewPostStore(state => state.drafts && state.drafts.findIndex(draft => draft.parentCastId?.hash === cast?.hash));

const {
allChannels: channels,
selectedChannelUrl
} = useAccountStore();

Expand Down Expand Up @@ -104,7 +103,6 @@ export const CastThreadView = ({ cast, onBack, fid, isActive }: CastThreadViewPr
<div className="min-w-0 flex-1">
<CastRow
cast={cast}
channels={channels}
showChannel={selectedChannelUrl === null}
isSelected={selectedCastIdx === idx}
isThreadView
Expand Down
7 changes: 7 additions & 0 deletions src/common/components/Embeds/OnchainEmbed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";

const OnchainEmbed = ({ url }: { url: string }) => {
return <div key={`onchain-embed-${url}`}>{url}</div>;
}

export default OnchainEmbed;
28 changes: 28 additions & 0 deletions src/common/components/Embeds/WarpcastEmbed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { CastType } from "@/common/constants/farcaster";
import { resolveWarpcastUrl } from "@/common/helpers/neynar";
import React, { useEffect, useState } from "react";
import { CastRow } from "../CastRow";
import isEmpty from "lodash.isempty";

const WarpcastEmbed = ({ url }: { url: string }) => {
const [cast, setCast] = useState<CastType>(null);

useEffect(() => {
const getData = async () => {
setCast(await resolveWarpcastUrl(url));
};

getData();
}, []);

return (
<div
key={`onchain-embed-${url}`}
className="border border-gray-600 rounded-sm"
>
{!isEmpty(cast) && <CastRow cast={cast} />}
</div>
);
}

export default WarpcastEmbed;
1 change: 0 additions & 1 deletion src/common/components/ReplyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ const ReplyModal = ({ parentCast, open, setOpen }: ReplyModalProps) => {
>
<CastRow
cast={parentCast}
channels={channels}
isSelected
/>
<NewPostEntry
Expand Down
23 changes: 22 additions & 1 deletion src/common/helpers/neynar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,28 @@ export const getNeynarFeedEndpoint = ({ fid, parentUrl, cursor, limit }: FeedEnd
return neynarEndpoint;
}


export const resolveWarpcastUrl = async (url: string): Promise<CastType> => {
const options = {
method: 'GET',
url: `${NEYNAR_API_URL}/v2/farcaster/cast`,
params: { type: 'url', identifier: url },
headers: { accept: 'application/json', api_key: VITE_NEYNAR_API_KEY }
};

return axios
.request(options)
.then(function(response) {
console.log(response.data);
return response.data.cast;
})
.catch(function(error) {
console.error(error);
return null;
});
}


export const getNeynarCastThreadEndpoint = ({ castHash, fid }: CastThreadEndpointProps): string => {
let neynarEndpoint = `${NEYNAR_API_URL}/v1/farcaster/all-casts-in-thread/?api_key=${VITE_NEYNAR_API_KEY}&threadHash=${castHash}`;

Expand All @@ -66,7 +88,6 @@ export const getNeynarNotificationsEndpoint = ({ fid, cursor, limit }: Notificat
return neynarEndpoint;
}

// https://invented-crayfish-e70.notion.site/GET-v2-farcaster-user-search-744565be2d2444bcbcbb2748be437998
// needs search with: &q=${query} to work
export const getNeynarUserSearchEndpoint = (viewerFid?: string): string => {
let neynarEndpoint = `${NEYNAR_API_URL}/v2/farcaster/user/search?api_key=${VITE_NEYNAR_API_KEY}`
Expand Down
1 change: 0 additions & 1 deletion src/pages/Feed/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ export default function Feed() {
className="border-b border-gray-700/40 relative flex items-center space-x-4 max-w-full md:max-w-2xl xl:max-w-3xl">
<CastRow
cast={item as CastType}
channels={channels}
showChannel={!selectedChannelUrl}
isSelected={selectedCastIdx === idx}
onSelect={() => onSelectCast(idx)}
Expand Down
1 change: 0 additions & 1 deletion src/pages/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ export default function Search() {
className="border-b border-gray-700 relative flex items-center space-x-4 py-2 max-w-full md:max-w-2xl xl:max-w-4xl">
<CastRow
cast={row}
channels={channels}
showChannel={selectedChannelIdx === null}
isSelected={selectedIdx === idx}
onSelect={() => null}
Expand Down

0 comments on commit a6ddd8a

Please sign in to comment.