Skip to content

Commit

Permalink
feat: support bsky mention on composing (#3901)
Browse files Browse the repository at this point in the history
  • Loading branch information
dudu0506 authored Feb 4, 2025
1 parent 40bf4d2 commit 1e3a709
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 54 deletions.
47 changes: 4 additions & 43 deletions src/app/(normal)/search/[...slug]/pages/SearchProfileContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { compact, uniqBy } from 'lodash-es';
import { ListInPage } from '@/components/ListInPage.js';
import { Empty } from '@/components/Search/Empty.js';
import { SearchableProfileItem } from '@/components/Search/SearchableProfileItem.js';
import { FireflyPlatform, ScrollListKey, Source } from '@/constants/enum.js';
import { formatSearchIdentities } from '@/helpers/formatSearchIdentities.js';
import { ScrollListKey, Source } from '@/constants/enum.js';
import { composeFireflyProfiles, formatSearchIdentities } from '@/helpers/formatSearchIdentities.js';
import { toFireflyPlatformId } from '@/helpers/isSameProfile.js';
import { createIndicator, createPageable } from '@/helpers/pageable.js';
import { runInSafeAsync } from '@/helpers/runInSafe.js';
Expand All @@ -16,48 +16,9 @@ import { BskySocialMediaProvider } from '@/providers/bsky/SocialMedia.js';
import { FireflyEndpointProvider } from '@/providers/firefly/Endpoint.js';
import { TwitterSocialMediaProvider } from '@/providers/twitter/SocialMedia.js';
import type { Profile as FireflyProfile } from '@/providers/types/Firefly.js';
import type { Profile } from '@/providers/types/SocialMedia.js';
import { useSearchStateStore } from '@/store/useSearchStore.js';

type ProfileWithRelated = { profile: FireflyProfile; related: FireflyProfile[] };

function composeProfiles(identities: ProfileWithRelated[], xProfiles: Profile[], bskyProfiles: Profile[]) {
return compact([
...identities,
...xProfiles.map((x) => {
const existed = identities.some(
({ profile }) => profile.platform === FireflyPlatform.Twitter && profile.platform_id === x.profileId,
);
if (existed) return null;

const matched = {
platform: FireflyPlatform.Twitter as const,
platform_id: x.profileId,
handle: x.handle,
name: x.displayName,
hit: true,
score: 0,
avatar: x.pfp,
};
return { profile: matched, related: [matched] };
}),
...bskyProfiles.map((x) => {
const bskyProfile = {
platform: FireflyPlatform.Bsky as const,
platform_id: x.profileId,
handle: x.handle,
name: x.displayName,
hit: true,
score: 0,
avatar: x.pfp,
};
return { profile: bskyProfile, related: [bskyProfile] };
}),
]);
}

const getSearchItemContent = (item: ProfileWithRelated) => {
const { profile, related } = item;
const getSearchItemContent = ({ profile, related }: { profile: FireflyProfile; related: FireflyProfile[] }) => {
return <SearchableProfileItem profile={profile} related={related} key={toFireflyPlatformId(profile)} />;
};

Expand Down Expand Up @@ -98,7 +59,7 @@ export function SearchProfileContent() {
...data,
twitterNextIndicator: twitterProfiles?.nextIndicator,
bskyNextIndicator: bskyProfiles?.nextIndicator,
data: composeProfiles(
data: composeFireflyProfiles(
formatSearchIdentities(data.data),
twitterProfiles?.data || [],
bskyProfiles?.data || [],
Expand Down
18 changes: 11 additions & 7 deletions src/components/Lexical/plugins/AtMentionsPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ import { Avatar } from '@/components/Avatar.js';
import { $createMentionNode } from '@/components/Lexical/nodes/MentionsNode.js';
import { SocialSourceIcon } from '@/components/SocialSourceIcon.js';
import { Tooltip } from '@/components/Tooltip.js';
import { FireflyPlatform, type SocialSource } from '@/constants/enum.js';
import { FireflyPlatform, type SocialSource, Source } from '@/constants/enum.js';
import { EMPTY_LIST, SORTED_SOCIAL_SOURCES } from '@/constants/index.js';
import { classNames } from '@/helpers/classNames.js';
import { formatSearchIdentities } from '@/helpers/formatSearchIdentities.js';
import { composeFireflyProfiles, formatSearchIdentities } from '@/helpers/formatSearchIdentities.js';
import { getSafeMentionQueryText } from '@/helpers/getMentionOriginalText.js';
import { getStampAvatarByProfileId } from '@/helpers/getStampAvatarByProfileId.js';
import { resolveSocialSourceFromFireflyPlatform } from '@/helpers/resolveSource.js';
import { useCompositePost } from '@/hooks/useCompositePost.js';
import { useCurrentProfileAll } from '@/hooks/useCurrentProfile.js';
import { BskySocialMediaProvider } from '@/providers/bsky/SocialMedia.js';
import { FireflyEndpointProvider } from '@/providers/firefly/Endpoint.js';
import type { Profile } from '@/providers/types/Firefly.js';

Expand Down Expand Up @@ -131,9 +132,9 @@ const MentionsTypeaheadMenuItem = memo<MentionsTypeaheadMenuItemProps>(function
)}
>
<Avatar alt={option.handle} className="h-7 w-7 rounded-full" src={option.pfp} size={32} />
<div className="flex flex-1 justify-between">
<div className="flex min-w-0 flex-1 justify-between">
<div className="flex flex-col truncate">
<div className="flex items-center text-sm">
<div className="truncate text-sm">
<span>{option.displayName}</span>
</div>
<span className="text-xs">@{option.handle}</span>
Expand Down Expand Up @@ -192,9 +193,12 @@ export function MentionsPlugin(): JSX.Element | null {
const data = await FireflyEndpointProvider.searchIdentity(debounceQuery, {
platforms: availableSources,
});
const bskyProfiles = availableSources.includes(Source.Bsky)
? await BskySocialMediaProvider.searchProfiles(debounceQuery)
: undefined;

if (!data) return EMPTY_LIST;
return formatSearchIdentities(data.data);
if (!data?.data && !bskyProfiles?.data) return EMPTY_LIST;
return composeFireflyProfiles(formatSearchIdentities(data.data), bskyProfiles?.data || []);
},
});

Expand All @@ -208,7 +212,7 @@ export function MentionsPlugin(): JSX.Element | null {
profile.platform_id,
profile.name,
profile.handle,
getStampAvatarByProfileId(source, profile.platform_id),
getStampAvatarByProfileId(source, profile.platform_id) || profile.avatar || '',
source,
related,
);
Expand Down
39 changes: 35 additions & 4 deletions src/helpers/formatSearchIdentities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,29 @@ import { compact, first } from 'lodash-es';

import { FireflyPlatform, Source } from '@/constants/enum.js';
import { SORTED_PROFILE_SOURCES } from '@/constants/index.js';
import { resolveFireflyPlatform } from '@/helpers/resolveFireflyPlatform.js';
import { resolveSocialSourceInUrl } from '@/helpers/resolveSourceInUrl.js';
import type { Profile, SearchProfileResponse } from '@/providers/types/Firefly.js';
import type { Profile as FireflyProfile, SearchProfileResponse } from '@/providers/types/Firefly.js';
import type { Profile } from '@/providers/types/SocialMedia.js';

const validPlatforms = [FireflyPlatform.Farcaster, FireflyPlatform.Lens, FireflyPlatform.Twitter];

function fixProfilePlatform(profile: Profile) {
function fixProfilePlatform(profile: FireflyProfile) {
if (!validPlatforms.includes(profile.platform)) {
return {
...profile,
platform: FireflyPlatform.Wallet,
// we use owner as platform_id for ens
platform_id: profile.owner || profile.platform_id,
} as Profile;
} as FireflyProfile;
}

return profile;
}

export function formatSearchIdentities(
identities: Required<SearchProfileResponse>['data']['list'],
): Array<{ profile: Profile; related: Profile[] }> {
): Array<{ profile: FireflyProfile; related: FireflyProfile[] }> {
return identities
.map((x) => {
const target = Object.values(x)
Expand All @@ -48,3 +50,32 @@ export function formatSearchIdentities(
})
.filter((handle) => !!handle);
}

export function composeFireflyProfiles(
identities: Array<{ profile: FireflyProfile; related: FireflyProfile[] }>,
...rest: Profile[][]
): Array<{ profile: FireflyProfile; related: FireflyProfile[] }> {
return compact([
...identities,
...rest.flatMap((profiles) => {
return profiles.map((x) => {
const platform = x.source === Source.Bsky ? FireflyPlatform.Bsky : resolveFireflyPlatform(x.source);
const existed = identities.some(
({ profile }) => profile.platform === platform && profile.platform_id === x.profileId,
);
if (existed || !platform) return null;

const matched = {
platform,
platform_id: x.profileId,
handle: x.handle,
name: x.displayName,
hit: true,
score: 0,
avatar: x.pfp,
};
return { profile: matched, related: [matched] };
});
}),
]);
}

0 comments on commit 1e3a709

Please sign in to comment.