mirror of
https://github.com/Equicord/Equicord.git
synced 2025-04-01 13:11:57 -04:00
Updated Pluginsettings.tsx (https://github.com/Vendicated/Vencord/pull/3293)
Added GithubRepos (https://github.com/Vendicated/Vencord/pull/3292) Also added Equicord Contrib to needed people
This commit is contained in:
parent
dc114666a8
commit
4269a8dd5b
12 changed files with 827 additions and 1 deletions
|
@ -276,7 +276,7 @@ export default function PluginSettings() {
|
|||
if (!search.length) return true;
|
||||
|
||||
return (
|
||||
plugin.name.toLowerCase().includes(search) ||
|
||||
plugin.name.toLowerCase().includes(search.replace(/\s+/g, "")) ||
|
||||
plugin.description.toLowerCase().includes(search) ||
|
||||
plugin.tags?.some(t => t.toLowerCase().includes(search))
|
||||
);
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
import { Flex } from "@components/Flex";
|
||||
import { openModal } from "@utils/modal";
|
||||
import { UserProfileStore, React, useEffect, useState } from "@webpack/common";
|
||||
import { fetchReposByUserId, fetchReposByUsername, fetchUserInfo, GitHubUserInfo } from "../services/githubApi";
|
||||
import { GitHubRepo } from "../types";
|
||||
import { settings } from "../utils/settings";
|
||||
import { RepoCard } from "./RepoCard";
|
||||
import { ReposModal } from "./ReposModal";
|
||||
|
||||
export function GitHubReposComponent({ id, theme }: { id: string, theme: string; }) {
|
||||
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 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;
|
||||
|
||||
// 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 <div className="vc-github-repos-loading">Loading repositories...</div>;
|
||||
if (error) return <div className="vc-github-repos-error">Error: {error}</div>;
|
||||
if (!repos.length) return null;
|
||||
|
||||
const topRepos = repos.slice(0, 3);
|
||||
|
||||
return (
|
||||
<div className="vc-github-repos-container">
|
||||
<div className="vc-github-repos-header">
|
||||
GitHub Repositories
|
||||
{userInfo && (
|
||||
<span className="vc-github-repos-count">
|
||||
{` (${topRepos.length}/${userInfo.totalRepos})`}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<Flex className="vc-github-repos-list" flexDirection="column">
|
||||
{topRepos.map(repo => (
|
||||
<RepoCard
|
||||
repo={repo}
|
||||
theme={theme}
|
||||
showStars={settings.store.showStars}
|
||||
showLanguage={settings.store.showLanguage}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
<div className="vc-github-repos-footer">
|
||||
<button
|
||||
className="vc-github-repos-show-more"
|
||||
onClick={openReposModal}
|
||||
>
|
||||
Show More
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
51
src/equicordplugins/githubRepos/components/RepoCard.tsx
Normal file
51
src/equicordplugins/githubRepos/components/RepoCard.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { Flex } from "@components/Flex";
|
||||
import { React } from "@webpack/common";
|
||||
import { RepoCardProps } from "../types";
|
||||
import { getLanguageColor } from "../utils/colors";
|
||||
import { Star } from "./icons/Star";
|
||||
|
||||
export function RepoCard({ repo, theme, showStars, showLanguage }: RepoCardProps) {
|
||||
const handleClick = () => window.open(repo.html_url, "_blank");
|
||||
|
||||
const renderStars = () => {
|
||||
if (!showStars) return null;
|
||||
|
||||
return (
|
||||
<div className="vc-github-repo-stars">
|
||||
<Star className="vc-github-repo-star-icon" />
|
||||
{repo.stargazers_count.toLocaleString()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderLanguage = () => {
|
||||
if (!showLanguage || !repo.language) return null;
|
||||
|
||||
return (
|
||||
<div className="vc-github-repo-language">
|
||||
<span
|
||||
className="vc-github-repo-language-color"
|
||||
style={{ backgroundColor: getLanguageColor(repo.language) }}
|
||||
/>
|
||||
{repo.language}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="vc-github-repo-card" onClick={handleClick}>
|
||||
<Flex className="vc-github-repo-header">
|
||||
<div className="vc-github-repo-name">{repo.name}</div>
|
||||
{renderStars()}
|
||||
</Flex>
|
||||
|
||||
{repo.description && (
|
||||
<div className="vc-github-repo-description">
|
||||
{repo.description}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{renderLanguage()}
|
||||
</div>
|
||||
);
|
||||
}
|
94
src/equicordplugins/githubRepos/components/ReposModal.tsx
Normal file
94
src/equicordplugins/githubRepos/components/ReposModal.tsx
Normal file
|
@ -0,0 +1,94 @@
|
|||
import { ModalContent, ModalFooter, ModalHeader, ModalRoot } from "@utils/modal";
|
||||
import { Button, Forms, React } from "@webpack/common";
|
||||
import { GitHubRepo } from "../types";
|
||||
import { getLanguageColor } from "../utils/colors";
|
||||
import { Star } from "./icons/Star";
|
||||
|
||||
interface ReposModalProps {
|
||||
repos: GitHubRepo[];
|
||||
username: string;
|
||||
rootProps: any;
|
||||
}
|
||||
|
||||
export function ReposModal({ repos, username, rootProps }: ReposModalProps) {
|
||||
const renderTableHeader = () => (
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Repository</th>
|
||||
<th>Description</th>
|
||||
<th>Language</th>
|
||||
<th>Stars</th>
|
||||
</tr>
|
||||
</thead>
|
||||
);
|
||||
|
||||
const renderTableRow = (repo: GitHubRepo) => (
|
||||
<tr key={repo.id} onClick={() => window.open(repo.html_url, "_blank")}>
|
||||
<td>
|
||||
<div className="vc-github-repos-table-name">{repo.name}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="vc-github-repos-table-description">
|
||||
{repo.description || ""}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{repo.language && (
|
||||
<div className="vc-github-repos-table-language">
|
||||
<span
|
||||
className="vc-github-repos-table-language-color"
|
||||
style={{ backgroundColor: getLanguageColor(repo.language) }}
|
||||
/>
|
||||
<span>{repo.language}</span>
|
||||
</div>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<div className="vc-github-repos-table-stars">
|
||||
<Star className="vc-github-repos-table-star-icon" />
|
||||
<span>{repo.stargazers_count.toLocaleString()}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
return (
|
||||
<ModalRoot className="vc-github-repos-modal" size="large" {...rootProps}>
|
||||
<ModalHeader>
|
||||
<Forms.FormTitle tag="h2" className="vc-github-repos-modal-title">
|
||||
{username}'s GitHub Repositories
|
||||
</Forms.FormTitle>
|
||||
</ModalHeader>
|
||||
<ModalContent className="vc-github-repos-modal-content">
|
||||
<div className="vc-github-repos-table-container">
|
||||
<table className="vc-github-repos-table">
|
||||
<colgroup>
|
||||
<col style={{ width: "20%" }} />
|
||||
<col style={{ width: "45%" }} />
|
||||
<col style={{ width: "15%" }} />
|
||||
<col style={{ width: "10%" }} />
|
||||
</colgroup>
|
||||
{renderTableHeader()}
|
||||
<tbody>
|
||||
{repos.map(renderTableRow)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ModalContent>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
onClick={() => window.open(`https://github.com/${username}?tab=repositories`, "_blank")}
|
||||
>
|
||||
View on GitHub
|
||||
</Button>
|
||||
<Button
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
look={Button.Looks.LINK}
|
||||
onClick={rootProps.onClose}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalRoot>
|
||||
);
|
||||
}
|
17
src/equicordplugins/githubRepos/components/icons/Star.tsx
Normal file
17
src/equicordplugins/githubRepos/components/icons/Star.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { React } from "@webpack/common";
|
||||
import { IconProps } from "../../types";
|
||||
|
||||
export function Star({ className, width = 16, height = 16 }: IconProps) {
|
||||
return (
|
||||
<svg
|
||||
className={className}
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 16 16"
|
||||
fill="currentColor"
|
||||
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" />
|
||||
</svg>
|
||||
);
|
||||
}
|
102
src/equicordplugins/githubRepos/index.tsx
Normal file
102
src/equicordplugins/githubRepos/index.tsx
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { findByCodeLazy } from "@webpack";
|
||||
import { React } from "@webpack/common";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { settings } from "./utils/settings";
|
||||
import { GitHubReposComponent } from "./components/GitHubReposComponent";
|
||||
import { Devs } from "@utils/constants";
|
||||
|
||||
const getProfileThemeProps = findByCodeLazy(".getPreviewThemeColors", "primaryColor:");
|
||||
|
||||
const logger = new Logger("GitHubRepos");
|
||||
logger.info("Plugin loaded");
|
||||
|
||||
const profilePopoutComponent = ErrorBoundary.wrap(
|
||||
(props: { user: any; displayProfile?: any; }) => {
|
||||
return (
|
||||
<GitHubReposComponent
|
||||
{...props}
|
||||
id={props.user.id}
|
||||
theme={getProfileThemeProps(props).theme}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{
|
||||
noop: true,
|
||||
onError: (err) => {
|
||||
logger.error("Error in profile popout component", err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default definePlugin({
|
||||
name: "GitHubRepos",
|
||||
description: "Displays a user's public GitHub repositories in their profile",
|
||||
authors: [Devs.talhakf],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: ".hasAvatarForGuild(null==",
|
||||
replacement: {
|
||||
match: /currentUser:\i,guild:\i}\)(?<=user:(\i),bio:null==(\i)\?.+?)/,
|
||||
replace: (m, user, profile) => {
|
||||
return `${m},$self.profilePopoutComponent({ user: ${user}, displayProfile: ${profile} })`;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "renderBio",
|
||||
replacement: {
|
||||
match: /renderBio\(\){.+?return (.*?)}/s,
|
||||
replace: (m, returnStatement) => {
|
||||
return `renderBio(){
|
||||
const originalReturn = ${returnStatement};
|
||||
const user = this.props.user;
|
||||
if (!user) return originalReturn;
|
||||
|
||||
try {
|
||||
const component = $self.profilePopoutComponent({
|
||||
user: user,
|
||||
displayProfile: this.props.displayProfile
|
||||
});
|
||||
|
||||
if (!originalReturn) return component;
|
||||
|
||||
return React.createElement(
|
||||
React.Fragment,
|
||||
null,
|
||||
originalReturn,
|
||||
component
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("[GitHubRepos] Error in bio patch:", err);
|
||||
return originalReturn;
|
||||
}
|
||||
}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
start() {
|
||||
logger.info("Plugin started");
|
||||
},
|
||||
|
||||
stop() {
|
||||
logger.info("Plugin stopped");
|
||||
},
|
||||
|
||||
profilePopoutComponent
|
||||
});
|
58
src/equicordplugins/githubRepos/services/githubApi.ts
Normal file
58
src/equicordplugins/githubRepos/services/githubApi.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { GitHubRepo } from "../types";
|
||||
import { Logger } from "@utils/Logger";
|
||||
|
||||
const logger = new Logger("GitHubRepos");
|
||||
|
||||
export interface GitHubUserInfo {
|
||||
username: string;
|
||||
totalRepos: number;
|
||||
}
|
||||
|
||||
export async function fetchUserInfo(username: string): Promise<GitHubUserInfo | null> {
|
||||
try {
|
||||
const userInfoUrl = `https://api.github.com/users/${username}`;
|
||||
const userInfoResponse = await fetch(userInfoUrl);
|
||||
|
||||
if (!userInfoResponse.ok) return null;
|
||||
|
||||
const userData = await userInfoResponse.json();
|
||||
return {
|
||||
username: userData.login,
|
||||
totalRepos: userData.public_repos
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Error fetching user info", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchReposByUserId(githubId: string, perPage: number = 30): Promise<GitHubRepo[] | null> {
|
||||
try {
|
||||
const apiUrl = `https://api.github.com/user/${githubId}/repos?sort=stars&direction=desc&per_page=${perPage}`;
|
||||
const response = await fetch(apiUrl);
|
||||
|
||||
if (!response.ok) return null;
|
||||
|
||||
const data = await response.json();
|
||||
return sortReposByStars(data);
|
||||
} catch (error) {
|
||||
logger.error("Error fetching repos by ID", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchReposByUsername(username: string, perPage: number = 30): Promise<GitHubRepo[]> {
|
||||
const apiUrl = `https://api.github.com/users/${username}/repos?sort=stars&direction=desc&per_page=${perPage}`;
|
||||
const response = await fetch(apiUrl);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error fetching repos by username: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return sortReposByStars(data);
|
||||
}
|
||||
|
||||
function sortReposByStars(repos: GitHubRepo[]): GitHubRepo[] {
|
||||
return repos.sort((a, b) => b.stargazers_count - a.stargazers_count);
|
||||
}
|
287
src/equicordplugins/githubRepos/styles.css
Normal file
287
src/equicordplugins/githubRepos/styles.css
Normal file
|
@ -0,0 +1,287 @@
|
|||
.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;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.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 {
|
||||
gap: 8px;
|
||||
overflow-y: auto;
|
||||
max-height: 400px;
|
||||
padding-right: 8px;
|
||||
margin-right: -8px;
|
||||
scrollbar-width: thin;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.vc-github-repos-list::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.vc-github-repos-list::-webkit-scrollbar-track {
|
||||
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 {
|
||||
margin-top: 12px;
|
||||
text-align: center;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid var(--background-modifier-accent);
|
||||
}
|
||||
|
||||
.vc-github-repos-view-all {
|
||||
color: var(--text-link);
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.vc-github-repos-view-all:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.vc-github-repos-show-more {
|
||||
background-color: transparent;
|
||||
color: var(--text-normal);
|
||||
border: 1px solid var(--background-modifier-accent);
|
||||
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-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 {
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--background-modifier-accent);
|
||||
background-color: transparent;
|
||||
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 {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.vc-github-repo-name {
|
||||
font-weight: 600;
|
||||
color: var(--header-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.vc-github-repo-fork-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.vc-github-repo-stars {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
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 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--text-muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.vc-github-repo-language-color {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.vc-github-repos-modal {
|
||||
width: 90%;
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.vc-github-repos-modal-title {
|
||||
color: var(--header-primary);
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.vc-github-repos-modal-content {
|
||||
padding: 16px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.vc-github-repos-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
color: var(--text-normal);
|
||||
font-size: 14px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.vc-github-repos-table colgroup {
|
||||
display: table-column-group;
|
||||
}
|
||||
|
||||
.vc-github-repos-table col {
|
||||
display: table-column;
|
||||
}
|
||||
|
||||
.vc-github-repos-table thead {
|
||||
border-bottom: 2px solid var(--background-modifier-accent);
|
||||
}
|
||||
|
||||
.vc-github-repos-table th {
|
||||
text-align: left;
|
||||
padding: 10px 16px;
|
||||
font-weight: 600;
|
||||
color: var(--header-primary);
|
||||
border-bottom: 2px solid var(--background-modifier-accent);
|
||||
}
|
||||
|
||||
.vc-github-repos-table th:last-child {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vc-github-repos-table tbody tr {
|
||||
border-bottom: 1px solid var(--background-modifier-accent);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.vc-github-repos-table tbody tr:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.vc-github-repos-table td {
|
||||
padding: 12px 16px;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid var(--background-modifier-accent);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-name {
|
||||
font-weight: 500;
|
||||
color: var(--header-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-fork-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.vc-github-repos-table-description {
|
||||
color: var(--text-normal);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-language {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-language-color {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-stars {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vc-github-repos-table-star-icon {
|
||||
color: var(--text-warning);
|
||||
}
|
22
src/equicordplugins/githubRepos/types/index.ts
Normal file
22
src/equicordplugins/githubRepos/types/index.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
export interface GitHubRepo {
|
||||
id: number;
|
||||
name: string;
|
||||
html_url: string;
|
||||
description: string;
|
||||
stargazers_count: number;
|
||||
language: string;
|
||||
fork: boolean;
|
||||
}
|
||||
|
||||
export interface IconProps {
|
||||
className?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export interface RepoCardProps {
|
||||
repo: GitHubRepo;
|
||||
theme: string;
|
||||
showStars: boolean;
|
||||
showLanguage: boolean;
|
||||
}
|
61
src/equicordplugins/githubRepos/utils/colors.ts
Normal file
61
src/equicordplugins/githubRepos/utils/colors.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
export function getLanguageColor(language: string): string {
|
||||
const colors: Record<string, string> = {
|
||||
"JavaScript": "#f1e05a",
|
||||
"TypeScript": "#3178c6",
|
||||
"Python": "#3572A5",
|
||||
"Java": "#b07219",
|
||||
"C#": "#178600",
|
||||
"C++": "#f34b7d",
|
||||
"C": "#555555",
|
||||
"HTML": "#e34c26",
|
||||
"CSS": "#563d7c",
|
||||
"PHP": "#4F5D95",
|
||||
"Ruby": "#701516",
|
||||
"Go": "#00ADD8",
|
||||
"Rust": "#dea584",
|
||||
"Swift": "#ffac45",
|
||||
"Kotlin": "#A97BFF",
|
||||
"Dart": "#00B4AB",
|
||||
"Shell": "#89e051",
|
||||
"PowerShell": "#012456",
|
||||
"Lua": "#000080",
|
||||
"Perl": "#0298c3",
|
||||
"R": "#198CE7",
|
||||
"Scala": "#c22d40",
|
||||
"Haskell": "#5e5086",
|
||||
"Elixir": "#6e4a7e",
|
||||
"Clojure": "#db5855",
|
||||
"Vue": "#41b883",
|
||||
"Svelte": "#ff3e00",
|
||||
"Jupyter Notebook": "#DA5B0B",
|
||||
"Assembly": "#6E4C13",
|
||||
"COBOL": "#004B85",
|
||||
"CoffeeScript": "#244776",
|
||||
"Crystal": "#000100",
|
||||
"D": "#BA595E",
|
||||
"F#": "#B845FC",
|
||||
"Fortran": "#4d41b1",
|
||||
"GLSL": "#5686A5",
|
||||
"Groovy": "#e69f56",
|
||||
"Julia": "#a270ba",
|
||||
"Markdown": "#083fa1",
|
||||
"MATLAB": "#bb92ac",
|
||||
"Objective-C": "#438eff",
|
||||
"OCaml": "#3be133",
|
||||
"Pascal": "#E3F171",
|
||||
"Prolog": "#74283c",
|
||||
"PureScript": "#1D222D",
|
||||
"Racket": "#3c5caa",
|
||||
"Raku": "#0000fb",
|
||||
"Reason": "#ff5847",
|
||||
"SCSS": "#c6538c",
|
||||
"Solidity": "#AA6746",
|
||||
"Tcl": "#e4cc98",
|
||||
"Verilog": "#b2b7f8",
|
||||
"VHDL": "#adb2cb",
|
||||
"WebAssembly": "#04133b",
|
||||
"Zig": "#ec915c"
|
||||
};
|
||||
|
||||
return colors[language] || "#858585";
|
||||
}
|
15
src/equicordplugins/githubRepos/utils/settings.ts
Normal file
15
src/equicordplugins/githubRepos/utils/settings.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { OptionType } from "@utils/types";
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
showStars: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show repository stars",
|
||||
default: true
|
||||
},
|
||||
showLanguage: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show repository language",
|
||||
default: true
|
||||
}
|
||||
});
|
|
@ -1020,6 +1020,10 @@ export const EquicordDevs = Object.freeze({
|
|||
name: "S€th",
|
||||
id: 1273447359417942128n
|
||||
},
|
||||
talhakf: {
|
||||
name: "talhakf",
|
||||
id: 1140716160560676976n
|
||||
},
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
// iife so #__PURE__ works correctly
|
||||
|
|
Loading…
Add table
Reference in a new issue