mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
Remove screen banning
This commit is contained in:
parent
80228a3bcc
commit
076cabfbfa
|
|
@ -547,7 +547,8 @@ export interface User {
|
|||
>;
|
||||
qWeaponPool: ColumnType<MainWeaponId[] | null, string | null, string | null>;
|
||||
plusSkippedForSeasonNth: number | null;
|
||||
noScreen: Generated<number>;
|
||||
// TODO: remove with migration
|
||||
// noScreen: Generated<number>;
|
||||
}
|
||||
|
||||
export interface UserResultHighlight {
|
||||
|
|
|
|||
|
|
@ -159,15 +159,3 @@ export async function findGroupById({
|
|||
})),
|
||||
} as GroupForMatch;
|
||||
}
|
||||
|
||||
export function groupMembersNoScreenSettings(groups: GroupForMatch[]) {
|
||||
return db
|
||||
.selectFrom("User")
|
||||
.select("User.noScreen")
|
||||
.where(
|
||||
"User.id",
|
||||
"in",
|
||||
groups.flatMap((group) => group.members.map((member) => member.id)),
|
||||
)
|
||||
.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ export async function settingsByUserId(userId: number) {
|
|||
"User.vc",
|
||||
"User.languages",
|
||||
"User.qWeaponPool",
|
||||
"User.noScreen",
|
||||
])
|
||||
.where("id", "=", userId)
|
||||
.executeTakeFirstOrThrow();
|
||||
|
|
@ -63,19 +62,3 @@ export function updateSendouQWeaponPool(args: {
|
|||
.where("User.id", "=", args.userId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
export function updateNoScreen({
|
||||
noScreen,
|
||||
userId,
|
||||
}: {
|
||||
noScreen: number;
|
||||
userId: number;
|
||||
}) {
|
||||
return db
|
||||
.updateTable("User")
|
||||
.set({
|
||||
noScreen,
|
||||
})
|
||||
.where("User.id", "=", userId)
|
||||
.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { z } from "zod";
|
|||
import { languagesUnified } from "~/modules/i18n/config";
|
||||
import {
|
||||
_action,
|
||||
checkboxValueToBoolean,
|
||||
modeShort,
|
||||
noDuplicates,
|
||||
safeJSONParse,
|
||||
|
|
@ -43,8 +42,4 @@ export const settingsActionSchema = z.union([
|
|||
z.array(weaponSplId).max(SENDOUQ_WEAPON_POOL_MAX_SIZE),
|
||||
),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_NO_SCREEN"),
|
||||
noScreen: z.preprocess(checkboxValueToBoolean, z.boolean()),
|
||||
}),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import { assertUnreachable } from "~/utils/types";
|
|||
import {
|
||||
SENDOUQ_PAGE,
|
||||
SENDOUQ_SETTINGS_PAGE,
|
||||
SPLATTERCOLOR_SCREEN_TWITTER_URL,
|
||||
navIconUrl,
|
||||
preferenceEmojiUrl,
|
||||
} from "~/utils/urls";
|
||||
|
|
@ -42,8 +41,6 @@ import { settingsActionSchema } from "../q-settings-schemas.server";
|
|||
import styles from "../q-settings.css";
|
||||
import { BANNED_MAPS } from "../banned-maps";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { Toggle } from "~/components/Toggle";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
|
|
@ -95,13 +92,6 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
|||
});
|
||||
break;
|
||||
}
|
||||
case "UPDATE_NO_SCREEN": {
|
||||
await QSettingsRepository.updateNoScreen({
|
||||
userId: user.id,
|
||||
noScreen: Number(data.noScreen),
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertUnreachable(data);
|
||||
}
|
||||
|
|
@ -126,7 +116,6 @@ export default function SendouQSettingsPage() {
|
|||
<WeaponPool />
|
||||
<VoiceChat />
|
||||
<Sounds />
|
||||
<Misc />
|
||||
</div>
|
||||
</Main>
|
||||
);
|
||||
|
|
@ -670,53 +659,3 @@ function SoundCheckboxes() {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Misc() {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const [checked, setChecked] = React.useState(Boolean(data.settings.noScreen));
|
||||
const { t } = useTranslation(["common", "q", "weapons"]);
|
||||
const fetcher = useFetcher();
|
||||
|
||||
return (
|
||||
<details>
|
||||
<summary className="q-settings__summary">
|
||||
<div>{t("q:settings.misc.header")}</div>
|
||||
</summary>
|
||||
<fetcher.Form method="post" className="mb-4 ml-2-5 stack sm">
|
||||
<div className="stack horizontal xs items-center">
|
||||
<Toggle
|
||||
checked={checked}
|
||||
setChecked={setChecked}
|
||||
id="noScreen"
|
||||
name="noScreen"
|
||||
/>
|
||||
<label className="mb-0" htmlFor="noScreen">
|
||||
{t("q:settings.avoid.label", {
|
||||
special: t("weapons:SPECIAL_19"),
|
||||
})}
|
||||
</label>
|
||||
</div>
|
||||
<FormMessage type="info">
|
||||
{t("q:settings.avoid.explanation")}{" "}
|
||||
<a
|
||||
href={SPLATTERCOLOR_SCREEN_TWITTER_URL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{t("q:settings.avoid.readMore")}
|
||||
</a>
|
||||
</FormMessage>
|
||||
<div className="mt-6">
|
||||
<SubmitButton
|
||||
size="big"
|
||||
className="mx-auto"
|
||||
_action="UPDATE_NO_SCREEN"
|
||||
state={fetcher.state}
|
||||
>
|
||||
{t("common:actions.save")}
|
||||
</SubmitButton>
|
||||
</div>
|
||||
</fetcher.Form>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,23 +434,6 @@
|
|||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.q-match__screen-legality svg {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.q-match__screen-legality .alert {
|
||||
padding-block: var(--s-1);
|
||||
padding-inline: var(--s-2-5);
|
||||
}
|
||||
|
||||
.q-match__screen-legality__button:focus-visible {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.q-match__screen-legality__button:focus-visible .alert {
|
||||
background-color: var(--bg-lighter);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
.q-match__teams-container {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
|
|
|||
|
|
@ -100,8 +100,6 @@ import { DiscordIcon } from "~/components/icons/Discord";
|
|||
import { useWindowSize } from "~/hooks/useWindowSize";
|
||||
import { joinListToNaturalString } from "~/utils/arrays";
|
||||
import { NewTabs } from "~/components/NewTabs";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import cachified from "@epic-web/cachified";
|
||||
import { refreshStreamsCache } from "~/features/sendouq-streams/core/streams.server";
|
||||
|
||||
export const meta: MetaFunction = (args) => {
|
||||
|
|
@ -432,22 +430,6 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
? reportedWeaponsByMatchId(matchId)
|
||||
: null;
|
||||
|
||||
const banScreen = !match.isLocked
|
||||
? await cachified({
|
||||
key: `matches-screen-ban-${match.id}`,
|
||||
cache,
|
||||
async getFreshValue() {
|
||||
const noScreenSettings =
|
||||
await QMatchRepository.groupMembersNoScreenSettings([
|
||||
groupAlpha,
|
||||
groupBravo,
|
||||
]);
|
||||
|
||||
return noScreenSettings.some((user) => user.noScreen);
|
||||
},
|
||||
})
|
||||
: null;
|
||||
|
||||
return {
|
||||
match: censoredMatch,
|
||||
matchChatCode: canAccessMatchChat ? match.chatCode : null,
|
||||
|
|
@ -455,7 +437,6 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
groupChatCode: groupChatCode(),
|
||||
groupAlpha: censoredGroupAlpha,
|
||||
groupBravo: censoredGroupBravo,
|
||||
banScreen,
|
||||
groupMemberOf: isTeamAlphaMember
|
||||
? ("ALPHA" as const)
|
||||
: isTeamBravoMember
|
||||
|
|
@ -1144,11 +1125,6 @@ function BottomSection({
|
|||
</FormWithConfirm>
|
||||
) : null;
|
||||
|
||||
const screenLegalityInfoElement =
|
||||
data.banScreen !== null ? (
|
||||
<ScreenLegalityInfo ban={data.banScreen} />
|
||||
) : null;
|
||||
|
||||
const chatHidden = chatRooms.length === 0;
|
||||
|
||||
if (!showMid && chatHidden) {
|
||||
|
|
@ -1161,7 +1137,6 @@ function BottomSection({
|
|||
<div className="stack horizontal lg items-center justify-center">
|
||||
{roomJoiningInfoElement}
|
||||
<div className="stack md">
|
||||
{screenLegalityInfoElement}
|
||||
{rulesButtonElement}
|
||||
{helpdeskButtonElement}
|
||||
{cancelMatchElement}
|
||||
|
|
@ -1211,7 +1186,6 @@ function BottomSection({
|
|||
>
|
||||
<div className="stack md">
|
||||
{roomJoiningInfoElement}
|
||||
{screenLegalityInfoElement}
|
||||
{rulesButtonElement}
|
||||
{helpdeskButtonElement}
|
||||
{cancelMatchElement}
|
||||
|
|
@ -1235,34 +1209,6 @@ function BottomSection({
|
|||
);
|
||||
}
|
||||
|
||||
function ScreenLegalityInfo({ ban }: { ban: boolean }) {
|
||||
const { t } = useTranslation(["q", "weapons"]);
|
||||
|
||||
return (
|
||||
<div className="q-match__screen-legality">
|
||||
<Popover
|
||||
triggerClassName="minimal tiny q-match__screen-legality__button"
|
||||
buttonChildren={
|
||||
<Alert variation={ban ? "ERROR" : "SUCCESS"}>
|
||||
<div className="stack xs horizontal items-center">
|
||||
<WeaponImage weaponSplId={401} width={30} variant="build" />
|
||||
<WeaponImage weaponSplId={6021} width={30} variant="build" />
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
>
|
||||
{ban
|
||||
? t("q:match.screen.ban", {
|
||||
special: t("weapons:SPECIAL_19"),
|
||||
})
|
||||
: t("q:match.screen.allowed", {
|
||||
special: t("weapons:SPECIAL_19"),
|
||||
})}
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function InfoWithHeader({ header, value }: { header: string; value: string }) {
|
||||
return (
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -37,15 +37,6 @@ export default function SendouqRules() {
|
|||
should be played out.
|
||||
</div>
|
||||
|
||||
<h2 className="text-lg mt-4">Unallowed weapons</h2>
|
||||
<div>
|
||||
If someone picks an unallowed weapon game can be canceled within 1
|
||||
minute by any player. For the replay everyone has to use the same
|
||||
weapons and gear except the player with unallowed weapon who should
|
||||
switch to the allowed variant of the weapon. For example had a player
|
||||
picked Foil Squeezer they need to play regular Squeezer in the replay.
|
||||
</div>
|
||||
|
||||
<h2 className="text-lg mt-4">Subs</h2>
|
||||
<div>
|
||||
There are no subs. If a player is unavailable to play from either team
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
useOutletContext,
|
||||
} from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import { Image, WeaponImage } from "~/components/Image";
|
||||
import { Image } from "~/components/Image";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
|
|
@ -32,8 +32,6 @@ import { NewTabs } from "~/components/NewTabs";
|
|||
import { ScoreReporterRosters } from "./ScoreReporterRosters";
|
||||
import { Chat, useChat } from "~/features/chat/components/Chat";
|
||||
import * as React from "react";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { CheckmarkIcon } from "~/components/icons/Checkmark";
|
||||
|
||||
export type Result = Unpacked<
|
||||
SerializeFrom<TournamentMatchLoaderData>["results"]
|
||||
|
|
@ -116,7 +114,6 @@ export function ScoreReporter({
|
|||
bestOf: data.match.bestOf,
|
||||
})}
|
||||
</>,
|
||||
data.banScreen !== null ? <ScreenBanIcons banned={data.banScreen} /> : null,
|
||||
];
|
||||
|
||||
const matchIsLockedError = actionData?.error === "locked";
|
||||
|
|
@ -203,20 +200,6 @@ export function ScoreReporter({
|
|||
);
|
||||
}
|
||||
|
||||
function ScreenBanIcons({ banned }: { banned: boolean }) {
|
||||
return (
|
||||
<div
|
||||
className={clsx("tournament-bracket__no-screen", {
|
||||
"tournament-bracket__no-screen__banned": banned,
|
||||
})}
|
||||
>
|
||||
{banned ? <CrossIcon /> : <CheckmarkIcon />}
|
||||
<WeaponImage weaponSplId={401} width={24} variant="build" />
|
||||
<WeaponImage weaponSplId={6021} width={24} variant="build" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FancyStageBanner({
|
||||
stage,
|
||||
infos,
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ import {
|
|||
import bracketStyles from "../tournament-bracket.css";
|
||||
import * as TournamentRepository from "~/features/tournament/TournamentRepository.server";
|
||||
import { logger } from "~/utils/logger";
|
||||
import cachified from "@epic-web/cachified";
|
||||
import { cache } from "~/utils/cache.server";
|
||||
|
||||
export const links: LinksFunction = () => [
|
||||
{
|
||||
|
|
@ -325,23 +323,6 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
const matchIsOver =
|
||||
match.opponentOne?.result === "win" || match.opponentTwo?.result === "win";
|
||||
|
||||
// not cache as performance optimization but instead
|
||||
// so that people don't change their setting mid-set
|
||||
const banScreen = !matchIsOver
|
||||
? await cachified({
|
||||
key: `tournament-screen-ban-${match.id}`,
|
||||
cache,
|
||||
async getFreshValue() {
|
||||
const noScreenSettings =
|
||||
await TournamentRepository.matchPlayersNoScreenSettings(
|
||||
match.players,
|
||||
);
|
||||
|
||||
return noScreenSettings.some((user) => user.noScreen);
|
||||
},
|
||||
})
|
||||
: null;
|
||||
|
||||
return {
|
||||
match: {
|
||||
...match,
|
||||
|
|
@ -351,7 +332,6 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
|
|||
seeds: resolveSeeds(),
|
||||
currentMap,
|
||||
modes: mapList?.map((map) => map.mode),
|
||||
banScreen,
|
||||
matchIsOver,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -103,20 +103,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tournament-bracket__no-screen {
|
||||
display: flex;
|
||||
gap: var(--s-0-5);
|
||||
}
|
||||
|
||||
.tournament-bracket__no-screen > svg {
|
||||
width: 24px;
|
||||
fill: var(--theme-success);
|
||||
}
|
||||
|
||||
.tournament-bracket__no-screen__banned > svg {
|
||||
fill: var(--theme-error);
|
||||
}
|
||||
|
||||
.tournament-bracket__during-match-actions {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
|
|
|
|||
|
|
@ -53,15 +53,3 @@ export async function findById(id: number) {
|
|||
|
||||
return { ...row, author };
|
||||
}
|
||||
|
||||
export function matchPlayersNoScreenSettings(players: { id: number }[]) {
|
||||
return db
|
||||
.selectFrom("User")
|
||||
.select("User.noScreen")
|
||||
.where(
|
||||
"User.id",
|
||||
"in",
|
||||
players.map((player) => player.id),
|
||||
)
|
||||
.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,11 +65,6 @@
|
|||
"settings.sounds.likeReceived": "Like received",
|
||||
"settings.sounds.groupNewMember": "Group new member",
|
||||
"settings.sounds.matchStarted": "Match started",
|
||||
"settings.misc.header": "Misc",
|
||||
"settings.banned": "Banned",
|
||||
"settings.avoid.label": "Avoid {{special}}",
|
||||
"settings.avoid.explanation": "Accessibility concerns related to the new special have been raised. Enabling this setting will make the special banned in SendouQ lobbies and tournament matches you play via sendou.ink.",
|
||||
"settings.avoid.readMore": "Read more about the issues here",
|
||||
|
||||
"looking.joiningGroupError": "Before joining another group, leave the current one",
|
||||
"looking.goToSettingsPrompt": "To help group finding set your weapon pool and voice chat status on the settings page",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user