Equicord/src/equicordplugins/githubRepos/components/GitHubReposComponent.tsx
MasterPepe a87e28709a
Added "repositories" tab in ModalV2 Profile (#665)
* Added "repositories" tab in ModalV2 Profile

* Add showRepositoryTab setting toggle

* fixes

---------

Co-authored-by: Accentaro <barmstrong210194@gmail.com>
Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
2026-01-21 13:10:09 -05:00

154 lines
5.3 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { BaseText } from "@components/BaseText";
import { Button, TextButton } from "@components/Button";
import { fetchReposByUserId, fetchReposByUsername, fetchUserInfo, GitHubUserInfo } from "@equicordplugins/githubRepos/githubApi";
import { GitHubRepo } from "@equicordplugins/githubRepos/types";
import { openModal } from "@utils/modal";
import { React, useEffect, UserProfileStore, useState } from "@webpack/common";
import { cl, settings } from "..";
import { RepoCard } from "./RepoCard";
import { ReposModal } from "./ReposModal";
export function GitHubReposComponent({ id, theme, variant = "popout" }: { id: string, theme: string; variant?: "popout" | "tab"; }) {
const [repos, setRepos] = useState<GitHubRepo[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [userInfo, setUserInfo] = useState<GitHubUserInfo | null>(null);
const [returnJustButton, setReturnJustButton] = useState(false);
const openReposModal = () => {
if (!userInfo) return;
const sortedRepos = [...repos].sort((a, b) => b.stargazers_count - a.stargazers_count);
openModal(props => (
<ReposModal
repos={sortedRepos}
username={userInfo.username}
rootProps={props}
/>
));
};
useEffect(() => {
const fetchData = async () => {
try {
const profile = UserProfileStore.getUserProfile(id);
if (!profile) {
setLoading(false);
return;
}
const connections = profile.connectedAccounts;
if (!connections?.length) {
setLoading(false);
return;
}
const githubConnection = connections.find(conn => conn.type === "github");
if (!githubConnection) {
setLoading(false);
return;
}
const username = githubConnection.name;
const userInfoData = await fetchUserInfo(username);
if (userInfoData) {
setUserInfo(userInfoData);
}
const githubId = githubConnection.id;
if (!settings.store.showInMiniProfile && variant !== "tab") setReturnJustButton(true);
// Try to fetch by ID first, fall back to username
const reposById = await fetchReposByUserId(githubId);
if (reposById) {
setRepos(reposById);
setLoading(false);
return;
}
const reposByUsername = await fetchReposByUsername(username);
setRepos(reposByUsername);
setLoading(false);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Failed to fetch repositories";
setError(errorMessage);
setLoading(false);
}
};
fetchData();
}, [id]);
if (loading) return;
<BaseText size="xs" weight="semibold" className={cl("loading")} >
Loading repositories...
</BaseText>;
if (error) return;
<BaseText size="xs" weight="semibold" className={cl("error")}>
Error: {error}
</BaseText>;
if (!repos.length) return null;
if (returnJustButton) {
return (
<Button
className={cl("button")}
size="small"
variant="secondary"
onClick={openReposModal}
>
Show GitHub Repositories
</Button>
);
}
const topRepos = variant === "tab" ? repos : repos.slice(0, 4);
return (
<div className={variant === "tab" ? `${cl("container")} ${cl("tab")}` : cl("container")}>
<BaseText size="xs" weight="semibold" className={cl("header")}>
GitHub Repositories
{userInfo && (
<span className={cl("count")}>
{variant === "tab"
? ` (${repos.length})`
: ` (Showing only top ${topRepos.length}/${userInfo.totalRepos})`
}
</span>
)}
</BaseText>
<div className={cl("list")}>
{topRepos.map(repo => (
<RepoCard
key={repo.id}
repo={repo}
showStars={settings.store.showStars}
showLanguage={settings.store.showLanguage}
variant={variant}
/>))
}
</div>
{variant !== "tab" && (
<div className={cl("footer")}>
<TextButton
className={cl("show-more")}
color="secondary"
onClick={openReposModal}
>
Show More
</TextButton>
</div>
)}
</div>
);
}