Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/Package/EntityCounter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Label } from '~/common/styleguide';
import tw from '~/util/tailwind';

type Props = {
count: number;
count: number | string;
style?: StyleProp<Style>;
};

Expand Down
2 changes: 1 addition & 1 deletion components/Package/PackageAuthor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Props = {
};

const authorContainerStyle = tw`flex flex-row items-center gap-3 bg-transparent`;
const labelStyle = tw`leading-[18px]`;
const labelStyle = tw`text-[13px] leading-[18px]`;
const sublabelStyle = tw`text-[11px] font-light text-palette-gray4 dark:text-secondary`;

export default function PackageAuthor({ author, compact }: Props) {
Expand Down
96 changes: 96 additions & 0 deletions components/Package/RepositoryContributors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { useMemo } from 'react';
import ContentLoader from 'react-content-loader';
import { View } from 'react-native';
import useSWR from 'swr';

import { A, H6Section, Label, useLayout } from '~/common/styleguide';
import EntityCounter from '~/components/Package/EntityCounter';
import UserAvatar from '~/components/Package/UserAvatar';
import Tooltip from '~/components/Tooltip';
import { type GitHubUser } from '~/types';
import { TimeRange } from '~/util/datetime';
import { pluralize } from '~/util/strings';
import tw from '~/util/tailwind';

type Props = {
fullName: string;
};

const LIMIT = 38;

export default function RepositoryContributors({ fullName }: Props) {
const { isSmallScreen } = useLayout();
const { data, isLoading } = useSWR(
`https://api.github.com/repos/${fullName}/contributors?per_page=${LIMIT}`,
(url: string) => fetch(url).then(res => res.json()),
{
dedupingInterval: TimeRange.HOUR * 1000,
revalidateOnFocus: false,
}
);

const contributors: GitHubUser[] = useMemo(
() =>
data?.sort((a: GitHubUser, b: GitHubUser) => (a.contributions < b.contributions ? 1 : -1)),
[data]
);

if (isLoading) {
return (
<>
<H6Section style={tw`mt-3 flex gap-1.5`}>Contributors</H6Section>
<ContentLoader
speed={2}
width="100%"
height={36}
backgroundColor={tw.prefixMatch('dark') ? '#2a2e36' : '#f3f3f3'}
foregroundColor={tw.prefixMatch('dark') ? '#383c42' : '#ecebeb'}>
<circle cx="18" cy="18" r="18" />
<circle cx="62" cy="18" r="18" />
<circle cx="106" cy="18" r="18" />
<circle cx="150" cy="18" r="18" />
<circle cx="194" cy="18" r="18" />
</ContentLoader>
</>
);
}

const hasMore = contributors?.length >= LIMIT;

return (
<>
<H6Section style={tw`mt-3 flex gap-1.5`}>
Contributors
<EntityCounter count={hasMore ? `${LIMIT}+` : contributors.length} />
{!isSmallScreen && hasMore && (
<A href={`https://github.com/${fullName}/contributors`} style={tw`ml-auto`}>
<Label style={tw`font-light`}>See all contributors</Label>
</A>
)}
</H6Section>
<View style={tw`flex-row flex-wrap items-start gap-2`}>
{contributors.map(contributor => (
<View style={tw`flex flex-row items-center gap-3 bg-transparent`} key={contributor.login}>
<Tooltip
sideOffset={2}
delayDuration={100}
trigger={
<View>
<A href={contributor.html_url} style={tw`contents`}>
<UserAvatar src={contributor.avatar_url} alt={`${contributor.login} avatar`} />
</A>
</View>
}>
<View>
<Label style={tw`text-[13px] leading-[18px]`}>{contributor.login}</Label>
<span style={tw`text-[11px] font-light text-palette-gray4 dark:text-secondary`}>
{contributor.contributions} {pluralize('contribution', contributor.contributions)}
</span>
</View>
</Tooltip>
</View>
))}
</View>
</>
);
}
13 changes: 8 additions & 5 deletions scenes/PackageOverviewScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import MorePackagesBox from '~/components/Package/MorePackagesBox';
import NotFound from '~/components/Package/NotFound';
import PackageAuthor from '~/components/Package/PackageAuthor';
import PackageHeader from '~/components/Package/PackageHeader';
import RepositoryContributors from '~/components/Package/RepositoryContributors';
import TopicsSection from '~/components/Package/TopicsSection';
import PageMeta from '~/components/PageMeta';
import { type NpmRegistryVersionData, type NpmUser, type PeerDependencyData } from '~/types';
Expand Down Expand Up @@ -80,9 +81,10 @@ export default function PackageOverviewScene({
</UL>
</>
)}
{!isSmallScreen && <MorePackagesBox library={library} />}
{!isSmallScreen && !!author && (
<>
<H6Section style={tw`mt-4`}>Author</H6Section>
<H6Section style={tw`mt-3`}>Author</H6Section>
<View style={tw`items-start`}>
<PackageAuthor author={author} />
</View>
Expand All @@ -91,7 +93,7 @@ export default function PackageOverviewScene({
{!isSmallScreen && maintainers && (
<>
<H6Section style={tw`mt-3 flex gap-1.5`}>
Contributors
Maintainers
<EntityCounter count={maintainers.length} />
</H6Section>
<View style={tw`flex-row flex-wrap items-start gap-2`}>
Expand All @@ -103,7 +105,7 @@ export default function PackageOverviewScene({
</View>
</>
)}
{!isSmallScreen && <MorePackagesBox library={library} />}
{!isSmallScreen && <RepositoryContributors fullName={library.github.fullName} />}
</View>
<View style={tw`flex-0.35 gap-4`} id="metadataContainer">
<View>
Expand Down Expand Up @@ -187,6 +189,7 @@ export default function PackageOverviewScene({
/>
<DependenciesSection title="Development dependencies" data={devDependencies} />
<DependenciesSection title="Engines" data={engines} />
{isSmallScreen && <MorePackagesBox library={library} />}
{isSmallScreen && !!author && (
<>
<H6Section>Author</H6Section>
Expand All @@ -198,7 +201,7 @@ export default function PackageOverviewScene({
{isSmallScreen && maintainers && (
<>
<H6Section style={tw`flex gap-1.5`}>
Contributors
Maintainer
<EntityCounter count={maintainers.length} />
</H6Section>
<View style={tw`flex-row flex-wrap items-start gap-2`}>
Expand All @@ -210,7 +213,7 @@ export default function PackageOverviewScene({
</View>
</>
)}
{isSmallScreen && <MorePackagesBox library={library} />}
{isSmallScreen && <RepositoryContributors fullName={library.github.fullName} />}
</View>
</View>
</ContentContainer>
Expand Down
23 changes: 23 additions & 0 deletions types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,26 @@ export type NightlyProgramData = {
maintainersUsernames: string[];
notes: string;
};

export type GitHubUser = {
avatar_url: string;
contributions: number;
events_url: string;
followers_url: string;
following_url: string;
gists_url: string;
gravatar_id: string;
html_url: string;
id: number;
login: string;
node_id: string;
organizations_url: string;
received_events_url: string;
repos_url: string;
site_admin: boolean;
starred_url: string;
subscriptions_url: string;
type: string;
url: string;
user_view_type: string;
};