diff --git a/.github/workflows/test_build.yml b/.github/workflows/test_build.yml index ef5167a..b53441c 100644 --- a/.github/workflows/test_build.yml +++ b/.github/workflows/test_build.yml @@ -19,14 +19,14 @@ jobs: uses: actions/checkout@v4 - name: Clone Vencord - run: git clone --depth=1 https://github.com/Vendicated/Vencord.git vencord + run: git clone --depth=1 https://github.com/Equicord/Equicord.git Equicord - - name: Move current repo into Vencord plugins + - name: Move current repo into Equicord plugins run: | PLUGIN_NAME=$(basename $GITHUB_REPOSITORY) - mkdir -p vencord/src/plugins/$PLUGIN_NAME + mkdir -p Equicord/src/plugins/$PLUGIN_NAME shopt -s extglob - cp -r !(vencord|.git|.github) vencord/src/plugins/$PLUGIN_NAME/ + cp -r !(Equicord|.git|.github) Equicord/src/plugins/$PLUGIN_NAME/ - name: Setup Node.js uses: actions/setup-node@v4 @@ -37,13 +37,13 @@ jobs: run: npm install -g pnpm - name: Install dependencies - working-directory: vencord + working-directory: Equicord run: pnpm install - name: Run pnpm build - working-directory: vencord + working-directory: Equicord run: pnpm build - name: Run pnpm buildWeb - working-directory: vencord + working-directory: Equicord run: pnpm buildWeb diff --git a/README.md b/README.md index 40fe858..44894d6 100644 --- a/README.md +++ b/README.md @@ -94,5 +94,5 @@ If you feel loved or interested in this project, you can leave us a **star** and
Lumi Logo -
@2023-2025 Lumi Comunity
+
@2023-2025 Lumi Community
diff --git a/docs/ru/README.md b/docs/ru/README.md index 26c0af3..0ab1975 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -3,10 +3,9 @@

Lumi Logo・fakeProfile

Плагин всё в одном для кастомизации вашего Discord-профиля
- en_US + en_US
Хотите перевести? Пожалуйста, сделайте форк и сделайте запрос вашего перевода.
-
Этот репозиторий является форком основного fakeProfile, пожалуйста оставьте звезду в нём.
@@ -16,7 +15,7 @@ CSS Discord Server
- +
Поддержка трёх клиентов
Pyoncord @@ -68,8 +67,8 @@ Если вам понравился или заинтересованы в этом проекте, - вы можете оставить **звезду** и поделиться этим проектом с людьми, которые хотят что и вы. Это будет отличной мотивацией для нас, чтобы продолжить разработку этого проекта, чтобы сделать даже лучше. Спасибо вам огромное.

- - Leave us a star + + Leave us a star

@@ -80,5 +79,5 @@
Lumi Logo -
@2023-2025 Lumi Comunity
+
@2023-2025 Lumi Community
diff --git a/index.css b/index.css index 6cf4d02..57743ea 100644 --- a/index.css +++ b/index.css @@ -30,4 +30,4 @@ .custom-nameplate ~ div { z-index: 1; -} +} \ No newline at end of file diff --git a/index.tsx b/index.tsx index b7d0e8b..e933a09 100644 --- a/index.tsx +++ b/index.tsx @@ -29,7 +29,7 @@ export default definePlugin({ name: "Sampath", id: 984015688807100419n, }], - dependencies: ["MessageDecorationsAPI", "BadgeAPI"], + dependencies: ["MessageDecorationsAPI", "BadgeAPI", "MemberListDecoratorsAPI"], start: async () => { enableStyle(style); useUsersProfileStore.getState().fetchBadges(); @@ -158,7 +158,7 @@ export default definePlugin({ { match: /(?<=\),nameplate:)(\i)/, replace: "$self.nameplate($1)" - } + }, ] }, { @@ -167,6 +167,15 @@ export default definePlugin({ match: /children:\[(?=.{0,100}\.MEMBER_LIST)/, replace: "$&arguments[0].banner," } + }, + { + find: ".WIDGETS_RTC_UPSELL_COACHMARK),", + replacement: [ + { + match: /(?<=\i\)\({avatarDecoration:)\i(?=,)(?<=currentUser:(\i).+?)/, + replace: "$self.useUserAvatarDecoration($1)??$&" + } + ] } ], profileDecodeHook(user: UserProfile) { @@ -244,12 +253,15 @@ export default definePlugin({ nameplate(nameplate: Nameplate | undefined) { return nameplate; }, - customnameplate(user: User, nameplate: Nameplate | undefined) { - const userId = user?.id; - const userData = useUsersProfileStore.getState().get(userId); + customnameplate(user: User | undefined, nameplate: Nameplate | undefined) { + if (!user) return null; + const userData = useUsersProfileStore.getState().get(user.id); if (userData && userData?.nameplate && settings.store.enableNameplate) { - const url = userData.nameplate; - const urlStr = typeof url === "object" ? JSON.stringify(url) : url; + const raw = userData.nameplate; + const urlStr = typeof raw === "object" && raw !== null + ? (raw as Nameplate).src + : raw as string; + if (!urlStr) return null; return (); } return null; diff --git a/lib/api.ts b/lib/api.ts index c5c4d40..91f5360 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -72,11 +72,11 @@ export interface Decors { } export const getEffects = async (): Promise => fetch(BASE_URL + "/profile-effects").then(c => c.json()); -export const getBadges = async (): Promise => fetch(BASE_URL + "/badges").then(c => c.json()); +export const getBadges = async (): Promise> => fetch(BASE_URL + "/badges").then(c => c.json()); export const getPresets = async (): Promise => fetch(BASE_URL + "/decorations").then(c => c.json()); -export const getUsers = async (ids?: string[]): Promise> => { +export const getUsers = async (ids?: string[]): Promise | null>> => { if (ids?.length === 0) return {}; const url = new URL(BASE_URL + "/users"); diff --git a/lib/stores/UsersProfileStore.ts b/lib/stores/UsersProfileStore.ts index 385af7d..41b4c50 100644 --- a/lib/stores/UsersProfileStore.ts +++ b/lib/stores/UsersProfileStore.ts @@ -51,54 +51,59 @@ export const useUsersProfileStore = proxyLazy(() => zustandCreate((set: any, get fetchBadges: debounce(async () => { if (!settings.store.enableCustomBadges) return; - const { addedBadges } = get(); - - addedBadges.forEach(badge => removeProfileBadge(badge)); - - const fetchedBadges = await getBadges(); - const newBadges = new Map( - Object.entries(fetchedBadges).map(([key, value]) => [key, value]) - ); - - const newAddedBadges: any[] = []; - - newBadges.forEach((userBadges, userId) => { - if (Array.isArray(userBadges)) { - userBadges.forEach(badge => { - const newBadge = { - id: "new_badges_profile_badge", - iconSrc: badge.badge, - description: badge.tooltip, - position: BadgePosition.START, - shouldShow: ({ userId: badgeUserId }) => badgeUserId === userId, - ...(badge.badge_id && { id: badge.badge_id }) - } satisfies ProfileBadge; - - addProfileBadge(newBadge); - newAddedBadges.push(newBadge); - }); - } - }); - - set({ - badges: newBadges, - addedBadges: newAddedBadges, - }); + try { + const { addedBadges } = get(); + + addedBadges.forEach(badge => removeProfileBadge(badge)); + + const fetchedBadges = await getBadges(); + + if (!fetchedBadges || typeof fetchedBadges !== "object" || Array.isArray(fetchedBadges)) return; + + const newBadges = new Map( + Object.entries(fetchedBadges).map(([key, value]) => [key, value]) + ); + + const newAddedBadges: any[] = []; + + newBadges.forEach((userBadges, userId) => { + if (Array.isArray(userBadges)) { + userBadges.forEach(badge => { + if (!badge?.badge) return; + const newBadge: ProfileBadge = { + id: badge.badge_id ?? badge.badge, + iconSrc: badge.badge, + description: badge.tooltip, + position: BadgePosition.START, + shouldShow: ({ userId: badgeUserId }) => badgeUserId === userId, + }; + addProfileBadge(newBadge); + newAddedBadges.push(newBadge); + }); + } + }); + + set({ + badges: newBadges, + addedBadges: newAddedBadges, + }); + } catch (e) { + console.error("[fakeProfile] fetchBadges failed:", e); + } }), fetchProfileEffects: debounce(async () => { - const { profileEffects } = get(); const fetchedProfileEffects = await getEffects(); - const newProfileEffects = new Map( - Object.entries(fetchedProfileEffects).map(([key, value]) => [key, value]) + if (!Array.isArray(fetchedProfileEffects)) return; + const newProfileEffects = new Map( + fetchedProfileEffects.map(effect => [effect.skuId, effect]) ); set({ profileEffects: newProfileEffects, }); - }), fetchDecorations: debounce(async () => { - const { decorations } = get(); const fetchedDecorations = await getPresets(); + if (!Array.isArray(fetchedDecorations)) return; const newDecorations = new Map( fetchedDecorations.map(decoration => [decoration.asset, decoration]) ); @@ -199,12 +204,13 @@ export function useUserAvatarDecoration(user?: User): Decoration | null | undefi return destructor; }, []); if (AvatarDecoration) { - const decoration = useUsersProfileStore.getState().decorations.get(AvatarDecoration); + let decoration = useUsersProfileStore.getState().decorations.get(AvatarDecoration); if (!decoration) { - useUsersProfileStore.getState().fetchDecorations(); - const decoration = useUsersProfileStore.getState().decorations.get(AvatarDecoration); - return { asset: AvatarDecoration, skuId: decoration.skuId, animated: decoration.animated }; + // fire-and-forget: hook can't be async; next render will pick up the result via subscription + void useUsersProfileStore.getState().fetchDecorations(); + decoration = useUsersProfileStore.getState().decorations.get(AvatarDecoration); } + if (!decoration) return null; return { asset: AvatarDecoration, skuId: decoration.skuId, animated: decoration.animated }; } return null; diff --git a/lib/types.ts b/lib/types.ts index 35a9804..23be3c3 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -7,6 +7,7 @@ import { User } from "@vencord/discord-types"; export interface UserProfile extends User { + bio: string; profileEffect: {}; userId: string; themeColors?: Array;