Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen1234 2026-03-19 07:56:49 -04:00
commit c6e542e595
No known key found for this signature in database
11 changed files with 71 additions and 48 deletions

View file

@ -1,6 +1,8 @@
.vc-text-base {
font-family: var(--font-primary);
color: var(--text-default);
line-height: normal;
/* Discord puts an insane default margin on p tags, so reset that here */
margin: 0;
}
@ -24,3 +26,7 @@
.vc-text-tabular-numbers {
font-variant-numeric: tabular-nums;
}
.vc-text-defaultColor {
color: var(--text-default);
}

View file

@ -82,6 +82,7 @@ export type BaseTextProps<Tag extends TextTag = "div"> = ComponentPropsWithoutRe
selectable?: boolean;
lineClamp?: number;
tabularNumbers?: boolean;
defaultColor?: boolean;
};
export function BaseText<T extends TextTag = "div">(props: BaseTextProps<T>): ReactNode {
@ -93,6 +94,7 @@ export function BaseText<T extends TextTag = "div">(props: BaseTextProps<T>): Re
selectable = false,
lineClamp,
tabularNumbers = false,
defaultColor = true,
children,
className,
style,
@ -107,6 +109,7 @@ export function BaseText<T extends TextTag = "div">(props: BaseTextProps<T>): Re
lineClamp === 1 && textCls("line-clamp-1"),
lineClamp != null && lineClamp > 1 && textCls("line-clamp"),
tabularNumbers && textCls("tabular-numbers"),
defaultColor && textCls("defaultColor"),
className
)}
style={{

View file

@ -52,7 +52,7 @@ export default definePlugin({
patches: [
{
find: ".DISPLAY_NAME_STYLES_COACHMARK),",
find: ".DISPLAY_NAME_STYLES_COACHMARK)",
replacement: {
// react.jsx)(AccountPanel, { ..., showTaglessAccountPanel: blah })
match: /(?<=\i\.jsxs?\)\()(\i),{(?=[^}]*?userTag:\i,occluded:)/,

View file

@ -75,11 +75,11 @@ export default definePlugin({
patches: [
{
find: ".WIDGETS_RTC_UPSELL_COACHMARK)",
find: "handleOpenSettingsContextMenu=",
group: true,
replacement: [
{
match: /(\.AVATAR,children:.+?renderPopout:\(?(\i).{0,5}=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/,
match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/,
replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalRenderPopout:()=>{${originalPopout}}})`
},
{

View file

@ -60,7 +60,7 @@ const settings = definePluginSettings({
randomisedLength: {
description: "Random characters length",
type: OptionType.NUMBER,
default: 10,
default: 7,
disabled: () => settings.store.method !== Methods.Random,
},
consistent: {
@ -134,7 +134,7 @@ export default definePlugin({
const newFilename = (() => {
switch (settings.store.method) {
case Methods.Random:
const chars = "ABCDEFabcdef0123456789";
const chars = "0123456789bdfhjkmnpqrstvwxz";
const returnedName = Array.from(
{ length: settings.store.randomisedLength },
() => chars[Math.floor(Math.random() * chars.length)]

View file

@ -87,7 +87,7 @@ export default definePlugin({
},
// Current user area, at bottom of channels/dm list
{
find: ".DISPLAY_NAME_STYLES_COACHMARK),",
find: ".DISPLAY_NAME_STYLES_COACHMARK)",
replacement: [
// Use Decor avatar decoration hook
{

View file

@ -26,7 +26,7 @@ import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { Guild } from "@vencord/discord-types";
import { findByCodeLazy, findByPropsLazy, findStoreLazy, mapMangledModuleLazy } from "@webpack";
import { ChannelStore, Menu } from "@webpack/common";
import { ChannelStore, Menu, UserStore } from "@webpack/common";
const { updateGuildNotificationSettings } = findByPropsLazy("updateGuildNotificationSettings");
const { toggleShowAllChannels } = mapMangledModuleLazy(".onboardExistingMember(", {
@ -175,5 +175,11 @@ export default definePlugin({
}
],
settings,
applyDefaultSettings
applyDefaultSettings,
flux: {
GUILD_JOIN_REQUEST_UPDATE({ guildId, request, status }) {
if (status === "APPROVED" && request.user_id === UserStore.getCurrentUser().id)
applyDefaultSettings(guildId);
}
}
});

View file

@ -24,7 +24,7 @@ import { canBlockReviewAuthor, canDeleteReview, canReportReview, cl, showToast }
import { openUserProfile } from "@utils/discord";
import { classes } from "@utils/misc";
import { findCssClassesLazy } from "@webpack";
import { Alerts, Parser, Timestamp, useState } from "@webpack/common";
import { Alerts, IconUtils, Parser, Timestamp, useState } from "@webpack/common";
import { openBlockModal } from "./BlockedUserModal";
import { BlockButton, DeleteButton, ReportButton } from "./MessageButton";
@ -116,8 +116,9 @@ export default function ReviewComponent({ review, refetch, profileId }: { review
<img
className={classes(AvatarClasses.avatar, AvatarClasses.clickable)}
onClick={openModal}
src={review.sender.profilePhoto || "/assets/1f0bfc0865d324c2587920a7d80c609b.png?size=128"}
src={review.sender.profilePhoto || IconUtils.getDefaultAvatarURL(review.sender.discordID)}
style={{ left: "0px", zIndex: 0 }}
onError={e => e.currentTarget.src = IconUtils.getDefaultAvatarURL(review.sender.discordID)}
/>
<div style={{ display: "inline-flex", justifyContent: "center", alignItems: "center" }}>
<span

View file

@ -62,13 +62,14 @@ export default function ReviewsView({
}: Props) {
const [signal, refetch] = useForceUpdater(true);
const [reviewData] = useAwaiter(() => getReviews(discordId, (page - 1) * REVIEWS_PER_PAGE), {
const [reviewData] = useAwaiter(() => getReviews(discordId, { offset: (page - 1) * REVIEWS_PER_PAGE }), {
fallbackValue: null,
deps: [refetchSignal, signal, page],
onSuccess: data => {
if (settings.store.hideBlockedUsers)
data!.reviews = data!.reviews?.filter(r => !RelationshipStore.isBlocked(r.sender.discordID));
data!.reviews.reverse();
scrollToTop?.();
onFetchReviews(data!);
}

View file

@ -29,7 +29,7 @@ import { useAwaiter } from "@utils/react";
import definePlugin from "@utils/types";
import { Guild, User } from "@vencord/discord-types";
import { findCssClassesLazy } from "@webpack";
import { Alerts, Clickable, Menu, Parser } from "@webpack/common";
import { Alerts, Clickable, IconUtils, Menu, Parser } from "@webpack/common";
import { Auth, initAuth, updateAuth } from "./auth";
import { openReviewsModal } from "./components/ReviewModal";
@ -157,7 +157,7 @@ export default definePlugin({
},
renderProfileComponent: ErrorBoundary.wrap(({ user, isSideBar = false }: { user: User; isSideBar?: boolean; }) => {
const [reviewData] = useAwaiter(() => getReviews(user.id, 0, true), { deps: [user.id], fallbackValue: null });
const [reviewData] = useAwaiter(() => getReviews(user.id, { limit: 4 }), { deps: [user.id], fallbackValue: null });
// Discord are masters at using a crap ton of html elements and css classes to create a simple ui that could have
// been made with less than half of the number of elements, so we have to do this insanity to replicate their ui
@ -166,37 +166,43 @@ export default definePlugin({
<ul className={ProfileCardClasses.cardsList} tabIndex={-1}>
<li className={ProfileCardClasses.firstCardContainer}>
<Clickable
className={classes(ProfileCardContainerClasses.breadcrumb, reviewData?.hasOptedOut ? cl("profile-popout-disabled") : null)}
className={classes(ProfileCardContainerClasses.breadcrumb, reviewData?.hasOptedOut && cl("profile-popout-disabled"))}
onClick={() => !reviewData?.hasOptedOut && openReviewsModal(user.id, user.username, ReviewType.User)}
>
<div className={classes(ProfileCardOverlayClasses.overlay, ProfileCardContainerClasses.innerContainer, ProfileCardClasses.card)}>
<Paragraph size={isSideBar ? "sm" : "xs"} weight="medium">User Reviews</Paragraph>
{reviewData?.hasOptedOut ? (
<Paragraph size={isSideBar ? "sm" : "xs"}>User disabled reviews</Paragraph>
) : !reviewData?.reviewCount ? (
<Paragraph size={isSideBar ? "sm" : "xs"}>No reviews yet</Paragraph>
) : !!reviewData?.reviewCount && (
<div className={ProfileCardContainerClasses.icons}>
{reviewData.reviews
.filter(review => review.id !== 0)
.slice(0, 4)
.reverse()
.map((review, idx) => {
const showCount = idx === 3 && reviewData.reviewCount > 4;
{!!reviewData?.reviewCount
? (
<div className={ProfileCardContainerClasses.icons}>
{reviewData.reviews
.filter(review => review.id !== 0)
.slice(0, 4)
.reverse()
.map((review, idx) => {
const showCount = idx === 3 && reviewData.reviewCount > 4;
return (
<div className={ProfileCardContainerClasses.icon} key={review.id}>
<img src={review.sender.profilePhoto} alt={review.sender.username} className={showCount ? ProfileCardContainerClasses.displayCount : undefined} />
{showCount && (
<div className={ProfileCardContainerClasses.displayCountText}>
<Span className={ProfileCardContainerClasses.displayCountTextColor} size="xs" weight="medium">+{reviewData.reviewCount - 3}</Span>
</div>
)}
</div>
);
})}
</div>
)}
return (
<div className={ProfileCardContainerClasses.icon} key={review.id}>
<img
src={review.sender.profilePhoto}
alt={review.sender.username}
className={showCount ? ProfileCardContainerClasses.displayCount : undefined}
onError={e => e.currentTarget.src = IconUtils.getDefaultAvatarURL(review.sender.discordID)}
/>
{showCount && (
<div className={ProfileCardContainerClasses.displayCountText}>
<Span className={ProfileCardContainerClasses.displayCountTextColor} size="xs" weight="medium" defaultColor={false}>
+{reviewData.reviewCount - 3}
</Span>
</div>
)}
</div>
);
})}
</div>
)
: <Paragraph size={isSideBar ? "sm" : "xs"}>{reviewData?.hasOptedOut ? "User opted out" : "No reviews yet"}</Paragraph>
}
</div>
</Clickable>
</li>

View file

@ -29,10 +29,10 @@ export const REVIEWS_PER_PAGE = 50;
export interface UserReviewsData {
message: string;
hasNextPage: boolean;
reviewCount: number;
reviews: Review[];
updated: boolean;
hasNextPage: boolean;
reviewCount: number;
hasOptedOut: boolean;
}
@ -48,15 +48,15 @@ async function rdbRequest(path: string, options: RequestInit = {}) {
});
}
export async function getReviews(id: string, offset = 0, isProfileComponent = false): Promise<UserReviewsData> {
export async function getReviews(id: string, { limit, offset = 0 }: { limit?: number; offset?: number; } = {}): Promise<UserReviewsData> {
let flags = 0;
if (!settings.store.showWarning) flags |= WarningFlag;
const params = new URLSearchParams({
flags: String(flags),
offset: String(offset),
...(isProfileComponent ? { limit: "4" } : {})
});
const params = new URLSearchParams();
if (flags) params.append("flags", String(flags));
if (offset) params.append("offset", String(offset));
if (limit) params.append("limit", String(limit));
const req = await fetch(`${API_URL}/users/${id}/reviews?${params}`);
const res = (req.ok)