fix(githubRepos): refactor and compactify (#219)
Some checks are pending
Test / Test (push) Waiting to run
Release / Build Equicord (push) Waiting to run

This commit is contained in:
panbread 2025-04-06 22:23:23 +04:00 committed by GitHub
parent a9ed6dbf7e
commit 5a7289e6c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 127 additions and 179 deletions

View file

@ -4,9 +4,9 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
import { Flex } from "@components/Flex"; import { classNameFactory } from "@api/Styles";
import { openModal } from "@utils/modal"; import { openModal } from "@utils/modal";
import { React, useEffect, UserProfileStore, useState } from "@webpack/common"; import { Button, React, Text, useEffect, UserProfileStore, useState } from "@webpack/common";
import { settings } from ".."; import { settings } from "..";
import { fetchReposByUserId, fetchReposByUsername, fetchUserInfo, GitHubUserInfo } from "../githubApi"; import { fetchReposByUserId, fetchReposByUsername, fetchUserInfo, GitHubUserInfo } from "../githubApi";
@ -21,6 +21,8 @@ export function GitHubReposComponent({ id, theme }: { id: string, theme: string;
const [userInfo, setUserInfo] = useState<GitHubUserInfo | null>(null); const [userInfo, setUserInfo] = useState<GitHubUserInfo | null>(null);
const [returnJustButton, setReturnJustButton] = useState(false); const [returnJustButton, setReturnJustButton] = useState(false);
const cl = classNameFactory("vc-github-repos-");
const openReposModal = () => { const openReposModal = () => {
if (!userInfo) return; if (!userInfo) return;
@ -86,51 +88,60 @@ export function GitHubReposComponent({ id, theme }: { id: string, theme: string;
fetchData(); fetchData();
}, [id]); }, [id]);
if (loading) return <div className="vc-github-repos-loading">Loading repositories...</div>; if (loading) return <Text variant="text-xs/semibold" className={cl("loading")} style={{ color: "var(--header-secondary)" }}>
if (error) return <div className="vc-github-repos-error">Error: {error}</div>; Loading repositories...</Text>;
if (error) return <Text variant="text-xs/semibold" className={cl("error")} style={{ color: "var(--text-danger)" }}>
Error: {error}</Text>;
if (!repos.length) return null; if (!repos.length) return null;
if (returnJustButton) { if (returnJustButton) {
return ( return (
<button <Button
className="vc-github-button" className={cl("button")}
size={Button.Sizes.SMALL}
look={Button.Looks.OUTLINED}
color={Button.Colors.TRANSPARENT}
onClick={openReposModal} onClick={openReposModal}
> >
Show GitHub Repositories Show GitHub Repositories
</button> </Button>
); );
} }
const topRepos = repos.slice(0, 3); const topRepos = repos.slice(0, 4);
return ( return (
<div className="vc-github-repos-container"> <div className={cl("container")}>
<div className="vc-github-repos-header"> <Text variant="text-xs/semibold" className={cl("header")} style={{ color: "var(--header-secondary)" }}>
GitHub Repositories GitHub Repositories
{userInfo && ( {userInfo && (
<span className="vc-github-repos-count"> <span className={cl("count")} style={{ color: "var(--text-muted)" }}>
{` (${topRepos.length}/${userInfo.totalRepos})`} {` (Showing only top ${topRepos.length}/${userInfo.totalRepos})`}
</span> </span>
)} )}
</div> </Text>
<Flex className="vc-github-repos-list" flexDirection="column"> <div className={cl("list")}>
{topRepos.map(repo => ( {topRepos.map(repo => (
<RepoCard <RepoCard
key={repo.id} key={repo.id}
repo={repo} repo={repo}
theme={theme}
showStars={settings.store.showStars} showStars={settings.store.showStars}
showLanguage={settings.store.showLanguage} showLanguage={settings.store.showLanguage}
/> />))
))} }
</Flex> </div>
<div className="vc-github-repos-footer"> <div className={cl("footer")}>
<button <Button
className="vc-github-repos-show-more" className={cl("show-more")}
size={Button.Sizes.SMALL}
look={Button.Looks.OUTLINED}
color={Button.Colors.TRANSPARENT}
onClick={openReposModal} onClick={openReposModal}
> >
Show More Show More
</button> </Button>
</div> </div>
</div> </div>
); );

View file

@ -4,23 +4,45 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
import { Flex } from "@components/Flex"; import { classNameFactory } from "@api/Styles";
import { React } from "@webpack/common"; import { React, Text, Tooltip } from "@webpack/common";
import { getLanguageColor } from "../colors"; import { getLanguageColor } from "../colors";
import { RepoCardProps } from "../types"; import { RepoCardProps } from "../types";
import { Star } from "./Star"; import { Star } from "./Star";
export function RepoCard({ repo, theme, showStars, showLanguage }: RepoCardProps) { export function RepoCard({ repo, showStars, showLanguage }: RepoCardProps) {
const handleClick = () => window.open(repo.html_url, "_blank"); const handleClick = () => window.open(repo.html_url, "_blank");
const cl = classNameFactory("vc-github-repo-");
const renderStars = () => { const renderStars = () => {
if (!showStars) return null; if (!showStars) return null;
return ( return (
<div className="vc-github-repo-stars"> <div className={cl("stars")}>
<Star className="vc-github-repo-star-icon" /> <Star className={cl("stars-icon")} />
{repo.stargazers_count.toLocaleString()} <Text variant="text-sm/normal" style={{ color: "var(--text-muted)" }}>{repo.stargazers_count.toLocaleString()}</Text>
</div>
);
};
const renderLink = () => {
return (
<div onClick={handleClick}>
<svg
className={cl("link")}
aria-hidden="true"
role="img"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="none"
viewBox="0 0 24 24"
style={{ cursor: "pointer" }}>
<path fill="var(--interactive-normal)" d="M8 5a1 1 0 0 0 0 2h7.59L5.29 17.3a1 1 0 1 0 1.42 1.4L17 8.42V16a1 1 0 1 0 2 0V6a1 1 0 0 0-1-1H8Z">
</path>
</svg>
</div> </div>
); );
}; };
@ -29,30 +51,47 @@ export function RepoCard({ repo, theme, showStars, showLanguage }: RepoCardProps
if (!showLanguage || !repo.language) return null; if (!showLanguage || !repo.language) return null;
return ( return (
<div className="vc-github-repo-language"> <div className={cl("language")}>
<span <span
className="vc-github-repo-language-color" className={cl("language-color")}
style={{ backgroundColor: getLanguageColor(repo.language) }} style={{ backgroundColor: getLanguageColor(repo.language) }}
/> />
{repo.language} <Text variant="text-sm/normal" style={{ color: "var(--text-muted)" }}>{repo.language}</Text>
{renderStars()}
</div > </div >
); );
}; };
return ( return (
<div className="vc-github-repo-card" onClick={handleClick}> <>
<Flex className="vc-github-repo-header"> {repo.description ? (
<div className="vc-github-repo-name">{repo.name}</div> <Tooltip text={repo.description} key={repo.id}>
{renderStars()} {({ onMouseLeave, onMouseEnter }) => (
</Flex> <div className={cl("card")}
onMouseLeave={onMouseLeave}
{repo.description && ( onMouseEnter={onMouseEnter}
<div className="vc-github-repo-description"> >
{repo.description} <div className={cl("header")}>
<Text variant="text-sm/medium" className={cl("name")} style={{ color: "var(--interactive-active)" }}>
{repo.name}
</Text>
{renderLink()}
</div> </div>
)}
{renderLanguage()} {renderLanguage()}
</div> </div>
)}
</Tooltip>
) : (
<div className={cl("card")}>
<div className={cl("header")}>
<Text variant="text-sm/medium" className={cl("name")} style={{ color: "var(--interactive-active)" }}>
{repo.name}
</Text>
{renderLink()}
</div>
{renderLanguage()}
</div>
)}
</>
); );
} }

View file

@ -15,7 +15,7 @@ export function Star({ className, width = 16, height = 16 }: IconProps) {
width={width} width={width}
height={height} height={height}
viewBox="0 0 16 16" viewBox="0 0 16 16"
fill="currentColor" fill="var(--text-warning)"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z" /> <path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z" />

View file

@ -12,7 +12,7 @@ import { EquicordDevs } from "@utils/constants";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { findByCodeLazy } from "@webpack"; import { findByCodeLazy } from "@webpack";
import { React } from "@webpack/common"; import { React, Text } from "@webpack/common";
import { User } from "discord-types/general"; import { User } from "discord-types/general";
import { GitHubReposComponent } from "./components/GitHubReposComponent"; import { GitHubReposComponent } from "./components/GitHubReposComponent";
@ -55,7 +55,8 @@ const ProfilePopoutComponent = ErrorBoundary.wrap(
noop: true, noop: true,
onError: err => { onError: err => {
logger.error("Error in profile popout component", err); logger.error("Error in profile popout component", err);
return null; return <Text variant="text-xs/semibold" className="vc-github-repos-error" style={{ color: "var(--text-danger)" }}>
Error, Failed to render GithubRepos</Text>;
} }
} }
); );
@ -63,7 +64,7 @@ const ProfilePopoutComponent = ErrorBoundary.wrap(
export default definePlugin({ export default definePlugin({
name: "GitHubRepos", name: "GitHubRepos",
description: "Displays a user's public GitHub repositories in their profile", description: "Displays a user's public GitHub repositories in their profile",
authors: [EquicordDevs.talhakf], authors: [EquicordDevs.talhakf, EquicordDevs.Panniku],
settings, settings,
patches: [ patches: [

View file

@ -1,157 +1,55 @@
.vc-github-repos-container { .vc-github-repos-container {
margin-top: 16px;
padding: 16px;
border-radius: 8px;
border: 1px solid var(--background-modifier-accent);
background-color: transparent;
max-height: 500px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} gap: 8px;
.vc-github-repos-header {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
color: var(--header-primary);
display: flex;
align-items: center;
}
.vc-github-repos-count {
font-size: 14px;
font-weight: 400;
color: var(--text-muted);
margin-left: 4px;
} }
.vc-github-repos-list { .vc-github-repos-list {
gap: 8px; display: grid;
overflow-y: auto; grid-template-columns: 260px 260px;
max-height: 400px; grid-gap: 16px;
padding-right: 8px;
margin-right: -8px;
scrollbar-width: thin;
flex: 1;
} }
.vc-github-repos-list::-webkit-scrollbar { /* stylelint-disable-next-line selector-class-pattern */
width: 8px; .biteSize_c0bea0 .vc-github-repos-list {
} display: flex;
flex-direction: column;
.vc-github-repos-list::-webkit-scrollbar-track { gap: 12px;
background: var(--scrollbar-thin-track);
border-radius: 10px;
}
.vc-github-repos-list::-webkit-scrollbar-thumb {
background: var(--scrollbar-thin-thumb);
border-radius: 10px;
}
.vc-github-repos-list::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-thin-thumb-hover);
} }
.vc-github-repos-footer { .vc-github-repos-footer {
margin-top: 12px; display: flex;
text-align: center; align-items: center;
padding-top: 8px; justify-content: center;
border-top: 1px solid var(--background-modifier-accent); margin-top: 2px;
padding-top: 12px;
border-top: 1px solid
var(--profile-body-divider-color, var(--background-modifier-accent));
} }
.vc-github-repos-view-all { .vc-github-repos-button,
color: var(--text-link);
font-size: 14px;
text-decoration: none;
}
.vc-github-repos-view-all:hover {
text-decoration: underline;
}
.vc-github-button,
.vc-github-repos-show-more { .vc-github-repos-show-more {
background-color: transparent; width: 100%;
color: var(--text-normal); border: 1px solid
border: 1px solid var(--background-modifier-accent); var(--profile-body-divider-color, var(--background-modifier-accent)) !important;
border-radius: 3px;
padding: 6px 12px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease;
}
.vc-github-button:hover,
.vc-github-repos-show-more:hover {
background-color: var(--background-modifier-hover);
border-color: var(--background-modifier-selected);
}
.vc-github-repos-loading,
.vc-github-repos-error {
color: var(--text-normal);
font-size: 14px;
margin: 8px 0;
}
.vc-github-repos-error {
color: var(--text-danger);
} }
.vc-github-repo-card { .vc-github-repo-card {
padding: 12px; padding: 8px;
border-radius: 6px; border-radius: var(--radius-xs);
border: 1px solid var(--background-modifier-accent); border: 1px solid
background-color: transparent; var(--profile-body-divider-color, var(--background-modifier-accent));
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease;
}
.vc-github-repo-card:hover {
background-color: var(--background-modifier-hover);
border-color: var(--background-modifier-selected);
} }
.vc-github-repo-header { .vc-github-repo-header {
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
}
.vc-github-repo-name {
font-weight: 600;
color: var(--header-primary);
display: flex; display: flex;
align-items: center; justify-content: space-between;
gap: 4px;
}
.vc-github-repo-fork-icon {
color: var(--text-muted);
} }
.vc-github-repo-stars { .vc-github-repo-stars {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
color: var(--text-muted);
font-size: 14px;
}
.vc-github-repo-star-icon {
color: var(--text-warning);
}
.vc-github-repo-description {
color: var(--text-normal);
font-size: 14px;
margin-bottom: 8px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
} }
.vc-github-repo-language { .vc-github-repo-language {
@ -163,9 +61,9 @@
} }
.vc-github-repo-language-color { .vc-github-repo-language-color {
width: 10px; width: var(--size-sm);
height: 10px; height: var(--size-sm);
border-radius: 50%; border-radius: var(--radius-round);
display: inline-block; display: inline-block;
} }

View file

@ -22,7 +22,6 @@ export interface IconProps {
export interface RepoCardProps { export interface RepoCardProps {
repo: GitHubRepo; repo: GitHubRepo;
theme: string;
showStars: boolean; showStars: boolean;
showLanguage: boolean; showLanguage: boolean;
} }