Fix SendouQ looking page flickers and animation glitches

Caused by rendering my instances of "useMainContentWidth" that return different values
This commit is contained in:
Kalle
2026-06-21 07:39:04 +03:00
parent 1cdbc5be94
commit 9df09bf4d5
2 changed files with 34 additions and 20 deletions

View File

@@ -17,7 +17,6 @@ import { useUser } from "~/features/auth/core/user";
import { MATCHES_COUNT_NEEDED_FOR_LEADERBOARD } from "~/features/leaderboards/leaderboards-constants";
import { ordinalToRoundedSp } from "~/features/mmr/mmr-utils";
import type { TieredSkill } from "~/features/mmr/tiered.server";
import { useMainContentWidth } from "~/hooks/useMainContentWidth";
import { languagesUnified } from "~/modules/i18n/config";
import { SPLATTERCOLOR_SCREEN_ID } from "~/modules/in-game-lists/weapon-ids";
import { inGameNameWithoutDiscriminator } from "~/utils/strings";
@@ -34,11 +33,7 @@ import type {
SQGroupMember,
SQOwnGroup,
} from "../core/SendouQ.server";
import {
FULL_GROUP_SIZE,
IS_Q_LOOKING_MOBILE_BREAKPOINT,
SENDOUQ,
} from "../q-constants";
import { FULL_GROUP_SIZE, SENDOUQ } from "../q-constants";
import { resolveFutureMatchModes } from "../q-utils";
import styles from "./GroupCard.module.css";
@@ -58,6 +53,7 @@ export function GroupCard({
showAddNote,
showNote = false,
ownGroup,
layout = "desktop",
}: {
group: SQGroup | SQOwnGroup;
action?: "LIKE" | "UNLIKE" | "GROUP_UP" | "MATCH_UP" | "MATCH_UP_RECHALLENGE";
@@ -68,6 +64,7 @@ export function GroupCard({
showAddNote?: SqlBool;
showNote?: boolean;
ownGroup?: SQOwnGroup;
layout?: "mobile" | "desktop";
}) {
const { t } = useTranslation(["q"]);
const user = useUser();
@@ -88,7 +85,11 @@ export function GroupCard({
const enableKicking = group.usersRole === "OWNER" && !displayOnly;
return (
<GroupCardContainer groupId={group.id} isOwnGroup={isOwnGroup}>
<GroupCardContainer
groupId={group.id}
isOwnGroup={isOwnGroup}
layout={layout}
>
<section className={styles.group} data-testid="sendouq-group-card">
{group.members ? (
<div className="stack md">
@@ -240,15 +241,14 @@ export function GroupCard({
function GroupCardContainer({
isOwnGroup,
groupId,
layout,
children,
}: {
isOwnGroup: boolean;
groupId: number;
layout: "mobile" | "desktop";
children: React.ReactNode;
}) {
const width = useMainContentWidth();
const layout = width < IS_Q_LOOKING_MOBILE_BREAKPOINT ? "mobile" : "desktop";
// we don't want it to animate
if (isOwnGroup) return <>{children}</>;

View File

@@ -229,15 +229,19 @@ function Groups() {
const width = useMainContentWidth();
if (!isHydrated) return null;
// width === 0 means the main content hasn't been measured yet; rendering the
// Flipper before measurement makes it snapshot the width-0 (mobile) default
// layout and then morph every card into the real layout on first navigation
if (!isHydrated || width === 0) return null;
const isMobile = width < IS_Q_LOOKING_MOBILE_BREAKPOINT;
const layout = isMobile ? "mobile" : "desktop";
const isFullGroup =
data.ownGroup && data.ownGroup.members.length === FULL_GROUP_SIZE;
const invitedGroupsDesktop = (
<div className="stack sm">
<ColumnHeader>
<ColumnHeader isMobile={isMobile}>
{t(
isFullGroup
? "q:looking.columns.challenged"
@@ -256,6 +260,7 @@ function Groups() {
action="UNLIKE"
showNote
ownGroup={data.ownGroup}
layout={layout}
/>
);
})}
@@ -264,7 +269,9 @@ function Groups() {
const ownGroupElement = data.ownGroup ? (
<div className="stack sm">
<ColumnHeader>{t("q:looking.columns.myGroup")}</ColumnHeader>
<ColumnHeader isMobile={isMobile}>
{t("q:looking.columns.myGroup")}
</ColumnHeader>
<GroupCard group={data.ownGroup} showNote ownGroup={data.ownGroup} />
{data.ownGroup.inviteCode ? (
<MemberAdder
@@ -330,7 +337,9 @@ function Groups() {
</SendouTabList>
<SendouTabPanel id="groups">
<div className="stack sm">
<ColumnHeader>{t("q:looking.columns.available")}</ColumnHeader>
<ColumnHeader isMobile={isMobile}>
{t("q:looking.columns.available")}
</ColumnHeader>
{(isMobile
? data.groups.filter(
(group) =>
@@ -353,6 +362,7 @@ function Groups() {
}
showNote
ownGroup={data.ownGroup}
layout={layout}
/>
);
})}
@@ -380,6 +390,7 @@ function Groups() {
action={action()}
showNote
ownGroup={data.ownGroup}
layout={layout}
/>
);
})}
@@ -390,7 +401,7 @@ function Groups() {
</div>
{!isMobile ? (
<div className="stack sm">
<ColumnHeader>
<ColumnHeader isMobile={isMobile}>
{t(
isFullGroup
? "q:looking.columns.challenges"
@@ -417,6 +428,7 @@ function Groups() {
action={action()}
showNote
ownGroup={data.ownGroup}
layout={layout}
/>
);
})}
@@ -427,11 +439,13 @@ function Groups() {
);
}
function ColumnHeader({ children }: { children: React.ReactNode }) {
const width = useMainContentWidth();
const isMobile = width < IS_Q_LOOKING_MOBILE_BREAKPOINT;
function ColumnHeader({
isMobile,
children,
}: {
isMobile: boolean;
children: React.ReactNode;
}) {
if (isMobile) return null;
return <div className={styles.header}>{children}</div>;