mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-27 13:45:27 -05:00
Remove trusted users Closes #1640
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { db } from "~/db/sql";
|
||||
import type { Tables, UserMapModePreferences } from "~/db/tables";
|
||||
import { modesShort, type MainWeaponId } from "~/modules/in-game-lists";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
|
||||
export async function settingsByUserId(userId: number) {
|
||||
const preferences = await db
|
||||
@@ -100,3 +101,35 @@ export function updateNoScreen({
|
||||
.where("User.id", "=", userId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
export function currentTeamByUserId(userId: number) {
|
||||
return db
|
||||
.selectFrom("TeamMember")
|
||||
.innerJoin("Team", "Team.id", "TeamMember.teamId")
|
||||
.select(["Team.name"])
|
||||
.where("TeamMember.userId", "=", userId)
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
export function findTrustedUsersByGiverId(trustGiverUserId: number) {
|
||||
return db
|
||||
.selectFrom("TrustRelationship")
|
||||
.innerJoin("User", "User.id", "TrustRelationship.trustReceiverUserId")
|
||||
.select(COMMON_USER_FIELDS)
|
||||
.where("TrustRelationship.trustGiverUserId", "=", trustGiverUserId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
export function deleteTrustedUser({
|
||||
trustGiverUserId,
|
||||
trustReceiverUserId,
|
||||
}: {
|
||||
trustGiverUserId: number;
|
||||
trustReceiverUserId: number;
|
||||
}) {
|
||||
return db
|
||||
.deleteFrom("TrustRelationship")
|
||||
.where("TrustRelationship.trustGiverUserId", "=", trustGiverUserId)
|
||||
.where("TrustRelationship.trustReceiverUserId", "=", trustReceiverUserId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { languagesUnified } from "~/modules/i18n/config";
|
||||
import {
|
||||
_action,
|
||||
checkboxValueToBoolean,
|
||||
id,
|
||||
modeShort,
|
||||
noDuplicates,
|
||||
safeJSONParse,
|
||||
@@ -73,4 +74,8 @@ export const settingsActionSchema = z.union([
|
||||
_action: _action("UPDATE_NO_SCREEN"),
|
||||
noScreen: z.preprocess(checkboxValueToBoolean, z.boolean()),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("REMOVE_TRUST"),
|
||||
userToRemoveTrustFromId: id,
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -44,6 +44,11 @@ import {
|
||||
SENDOUQ_WEAPON_POOL_MAX_SIZE,
|
||||
} from "../q-settings-constants";
|
||||
import { settingsActionSchema } from "../q-settings-schemas.server";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { UsersIcon } from "~/components/icons/Users";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Trans } from "react-i18next";
|
||||
|
||||
import "../q-settings.css";
|
||||
|
||||
@@ -100,6 +105,13 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "REMOVE_TRUST": {
|
||||
await QSettingsRepository.deleteTrustedUser({
|
||||
trustGiverUserId: user.id,
|
||||
trustReceiverUserId: data.userToRemoveTrustFromId,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertUnreachable(data);
|
||||
}
|
||||
@@ -113,6 +125,8 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
|
||||
return {
|
||||
settings: await QSettingsRepository.settingsByUserId(user.id),
|
||||
trusted: await QSettingsRepository.findTrustedUsersByGiverId(user.id),
|
||||
team: await QSettingsRepository.currentTeamByUserId(user.id),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -124,6 +138,7 @@ export default function SendouQSettingsPage() {
|
||||
<WeaponPool />
|
||||
<VoiceChat />
|
||||
<Sounds />
|
||||
<TrustedUsers />
|
||||
<Misc />
|
||||
</div>
|
||||
</Main>
|
||||
@@ -587,8 +602,10 @@ function Sounds() {
|
||||
<span>{t("q:settings.sounds.header")}</span> <SpeakerFilledIcon />
|
||||
</div>
|
||||
</summary>
|
||||
{isMounted && <SoundCheckboxes />}
|
||||
{isMounted && <SoundSlider />}
|
||||
<div className="mb-4">
|
||||
{isMounted && <SoundCheckboxes />}
|
||||
{isMounted && <SoundSlider />}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
@@ -689,6 +706,80 @@ function SoundSlider() {
|
||||
);
|
||||
}
|
||||
|
||||
function TrustedUsers() {
|
||||
const { t } = useTranslation(["q"]);
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<details>
|
||||
<summary className="q-settings__summary">
|
||||
<span>{t("q:settings.trusted.header")}</span> <UsersIcon />
|
||||
</summary>
|
||||
<div className="mb-4">
|
||||
{data.trusted.length > 0 ? (
|
||||
<>
|
||||
<div className="stack md mt-2">
|
||||
{data.trusted.map((trustedUser) => {
|
||||
return (
|
||||
<div
|
||||
key={trustedUser.id}
|
||||
className="stack horizontal xs items-center"
|
||||
>
|
||||
<Avatar user={trustedUser} size="xxs" />
|
||||
<div className="text-sm font-semi-bold">
|
||||
{trustedUser.discordName}
|
||||
</div>
|
||||
<FormWithConfirm
|
||||
dialogHeading={t("q:settings.trusted.confirm", {
|
||||
name: trustedUser.discordName,
|
||||
})}
|
||||
fields={[
|
||||
["_action", "REMOVE_TRUST"],
|
||||
["userToRemoveTrustFromId", trustedUser.id],
|
||||
]}
|
||||
deleteButtonText="Remove"
|
||||
>
|
||||
<Button
|
||||
className="build__small-text"
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
type="submit"
|
||||
>
|
||||
<TrashIcon className="build__icon" />
|
||||
</Button>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<FormMessage type="info">
|
||||
{t("q:settings.trusted.trustedExplanation")}
|
||||
</FormMessage>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<FormMessage type="info" className="mb-2">
|
||||
{t("q:settings.trusted.noTrustedExplanation")}
|
||||
</FormMessage>
|
||||
)}
|
||||
{data.team ? (
|
||||
<FormMessage type="info" className="mb-2">
|
||||
<Trans
|
||||
i18nKey="q:settings.trusted.teamExplanation"
|
||||
t={t}
|
||||
values={{
|
||||
name: data.team.name,
|
||||
}}
|
||||
>
|
||||
In addition to the users above, a member of your team{" "}
|
||||
<b>{data.team.name}</b> can you add you directly.
|
||||
</Trans>
|
||||
</FormMessage>
|
||||
) : null}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
function Misc() {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const [checked, setChecked] = React.useState(Boolean(data.settings.noScreen));
|
||||
|
||||
@@ -73,6 +73,11 @@
|
||||
"settings.misc.header": "Misc",
|
||||
"settings.banned": "Banned",
|
||||
"settings.avoid.label": "Avoid {{special}}",
|
||||
"settings.trusted.header": "Trusted users",
|
||||
"settings.trusted.confirm": "Remove {{name}} from trusted users?",
|
||||
"settings.trusted.trustedExplanation": "Trusted users can add you to groups and tournament teams directly. If removed from this list, in the future you need to join via a link they share.",
|
||||
"settings.trusted.noTrustedExplanation": "You don't currently trust any users. Users can be trusted when you join their SendouQ group or tournament team via a link. Trusted users can add you to groups and tournament teams directly.",
|
||||
"settings.trusted.teamExplanation": "In addition to the users above, a member of your team <2>{{name}}</2> can you add you directly.",
|
||||
|
||||
"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",
|
||||
|
||||
Reference in New Issue
Block a user