mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-24 20:27:13 -05:00
Fix SQ weapon etc. cache not purged on match profile change
This commit is contained in:
@@ -8,19 +8,19 @@ import {
|
||||
} from "../q-constants";
|
||||
import { refreshSendouQInstance, SendouQ } from "./SendouQ.server";
|
||||
|
||||
/** Cancels every pending challenge involving the user's active full group. Partial groups merge rather than start a match on accept, so their preferences are not locked in yet. */
|
||||
/** Cancels every pending challenge involving the user's active full group, returning whether any were, which also means the instance was refreshed. Partial groups merge rather than start a match on accept, so their preferences are not locked in yet. */
|
||||
export async function cancelActiveGroupLikes(userId: number) {
|
||||
const ownGroup = SendouQ.findOwnGroup(userId);
|
||||
if (!ownGroup) return;
|
||||
if (ownGroup.status !== "ACTIVE" || ownGroup.matchId) return;
|
||||
if (ownGroup.members.length !== FULL_GROUP_SIZE) return;
|
||||
if (!ownGroup) return false;
|
||||
if (ownGroup.status !== "ACTIVE" || ownGroup.matchId) return false;
|
||||
if (ownGroup.members.length !== FULL_GROUP_SIZE) return false;
|
||||
|
||||
const likes = await SQGroupRepository.findAllLikesByGroupId(ownGroup.id);
|
||||
const affectedGroupIds = R.unique([
|
||||
...likes.given.map((like) => like.groupId),
|
||||
...likes.received.map((like) => like.groupId),
|
||||
]);
|
||||
if (affectedGroupIds.length === 0) return;
|
||||
if (affectedGroupIds.length === 0) return false;
|
||||
|
||||
await SQGroupRepository.deleteAllLikesByGroupId(ownGroup.id);
|
||||
|
||||
@@ -40,4 +40,6 @@ export async function cancelActiveGroupLikes(userId: number) {
|
||||
) ?? [],
|
||||
),
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
76
app/features/settings/actions/settings.server.test.ts
Normal file
76
app/features/settings/actions/settings.server.test.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import * as SQGroupFactory from "~/db/seed/factories/SQGroupFactory";
|
||||
import * as UserFactory from "~/db/seed/factories/UserFactory";
|
||||
import * as MatchProfileRepository from "~/features/match-profile/MatchProfileRepository.server";
|
||||
import {
|
||||
refreshSendouQInstance,
|
||||
SendouQ,
|
||||
} from "~/features/sendouq/core/SendouQ.server";
|
||||
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
||||
import { wrappedAction } from "~/utils/Test";
|
||||
import type { settingsActionSchema } from "../settings-schemas.server";
|
||||
import { action } from "./settings.server";
|
||||
|
||||
vi.mock("~/features/chat/ChatSystemMessage.server", () => ({
|
||||
send: vi.fn(),
|
||||
notifyStatusChanged: vi.fn(),
|
||||
notifyNotificationsChanged: vi.fn(),
|
||||
}));
|
||||
|
||||
const OLD_WEAPON_ID: MainWeaponId = 0;
|
||||
const NEW_WEAPON_ID: MainWeaponId = 40;
|
||||
|
||||
const settingsAction = wrappedAction<typeof settingsActionSchema>({
|
||||
action,
|
||||
isJsonSubmission: true,
|
||||
});
|
||||
|
||||
const users = UserFactory.pool();
|
||||
|
||||
const actorId = () => users.id(1);
|
||||
|
||||
const updateWeaponPool = (weaponId: MainWeaponId) =>
|
||||
settingsAction(
|
||||
{
|
||||
_action: "UPDATE_MATCH_PROFILE",
|
||||
mapModePreferences: { modes: [], pool: [] },
|
||||
weaponPool: [{ id: weaponId, isFavorite: false }],
|
||||
vc: "NO",
|
||||
languages: [],
|
||||
noScreen: false,
|
||||
},
|
||||
{ user: actorId() },
|
||||
);
|
||||
|
||||
const ownWeaponsInQueue = () =>
|
||||
SendouQ.findOwnGroup(actorId())
|
||||
?.members.find((member) => member.id === actorId())
|
||||
?.weapons?.map((weapon) => weapon.weaponSplId);
|
||||
|
||||
describe("settings action: UPDATE_MATCH_PROFILE", () => {
|
||||
beforeEach(async () => {
|
||||
await users.create(1, null, {
|
||||
matchProfile: { weaponPool: [{ id: OLD_WEAPON_ID, isFavorite: false }] },
|
||||
});
|
||||
});
|
||||
|
||||
test("a new weapon pool is shown to the queue right away", async () => {
|
||||
await SQGroupFactory.create({ memberUserIds: [actorId()] });
|
||||
await refreshSendouQInstance();
|
||||
|
||||
await updateWeaponPool(NEW_WEAPON_ID);
|
||||
|
||||
expect(ownWeaponsInQueue()).toEqual([NEW_WEAPON_ID]);
|
||||
});
|
||||
|
||||
test("updates the weapon pool of a user who is not queueing", async () => {
|
||||
await updateWeaponPool(NEW_WEAPON_ID);
|
||||
|
||||
const weaponPool = await MatchProfileRepository.findWeaponPoolByUserId(
|
||||
actorId(),
|
||||
);
|
||||
expect(weaponPool.map((weapon) => weapon.weaponSplId)).toEqual([
|
||||
NEW_WEAPON_ID,
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,16 @@
|
||||
import type { ActionFunctionArgs } from "react-router";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import * as ChatSystemMessage from "~/features/chat/ChatSystemMessage.server";
|
||||
import * as MatchProfileRepository from "~/features/match-profile/MatchProfileRepository.server";
|
||||
import { cancelActiveGroupLikes } from "~/features/sendouq/core/likes.server";
|
||||
import {
|
||||
refreshSendouQInstance,
|
||||
SendouQ,
|
||||
} from "~/features/sendouq/core/SendouQ.server";
|
||||
import {
|
||||
SENDOUQ_LOOKING_CHANNEL,
|
||||
sqGroupChannel,
|
||||
} from "~/features/sendouq/q-constants";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { parseFormData } from "~/form/parse.server";
|
||||
import { isSupporter } from "~/modules/permissions/utils";
|
||||
@@ -78,8 +87,13 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
});
|
||||
|
||||
// challenges are based on the preferences shown at the time, so changing them undoes pending ones
|
||||
if (mapModePreferencesChanged || noScreenChanged) {
|
||||
await cancelActiveGroupLikes(user.id);
|
||||
const likesCancelled =
|
||||
mapModePreferencesChanged || noScreenChanged
|
||||
? await cancelActiveGroupLikes(user.id)
|
||||
: false;
|
||||
|
||||
if (!likesCancelled) {
|
||||
await showMatchProfileToOthers(user.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -90,3 +104,16 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/** SendouQ pages serve group members from the in-memory instance, so a match profile change stays invisible to everyone else till it is rebuilt. */
|
||||
async function showMatchProfileToOthers(userId: number) {
|
||||
const ownGroup = SendouQ.findOwnGroup(userId);
|
||||
if (!ownGroup) return;
|
||||
|
||||
await refreshSendouQInstance();
|
||||
|
||||
ChatSystemMessage.send([
|
||||
{ channel: sqGroupChannel(ownGroup.id) },
|
||||
{ channel: SENDOUQ_LOOKING_CHANNEL },
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
navItem: sendouq
|
||||
type: bug
|
||||
---
|
||||
Changes to your SendouQ info (weapon pool, languages, voice chat) now show up to other players right away instead of after a delay
|
||||
Reference in New Issue
Block a user