feat: add reporting UI

This commit is contained in:
Paul Makles 2023-02-22 17:13:43 +01:00
parent 46eec5a132
commit 7d544c82ab
No known key found for this signature in database
GPG key ID: 5059F398521BB0F6
6 changed files with 198 additions and 9 deletions

2
external/lang vendored

@ -1 +1 @@
Subproject commit 5bf84e27074daeab3055f299e54be955aae5042d
Subproject commit 79d9b042866d466f39e3f4d053833416137491f8

View file

@ -41,6 +41,7 @@ import MFARecovery from "./components/MFARecovery";
import ModifyAccount from "./components/ModifyAccount";
import OutOfDate from "./components/OutOfDate";
import PendingFriendRequests from "./components/PendingFriendRequests";
import ReportContent from "./components/Report";
import ServerIdentity from "./components/ServerIdentity";
import ServerInfo from "./components/ServerInfo";
import ShowToken from "./components/ShowToken";
@ -276,4 +277,5 @@ export const modalController = new ModalControllerExtended({
sign_out_sessions: SignOutSessions,
user_picker: UserPicker,
user_profile: UserProfile,
report: ReportContent,
});

View file

@ -0,0 +1,125 @@
import { API, Message as MessageInterface, User } from "revolt.js";
import { Text } from "preact-i18n";
import { ModalForm, Row } from "@revoltchat/ui";
import Message from "../../../components/common/messaging/Message";
import UserShort from "../../../components/common/user/UserShort";
import { useClient } from "../../client/ClientController";
import { ModalProps } from "../types";
const CONTENT_REASONS: API.ContentReportReason[] = [
"NoneSpecified",
"Illegal",
"PromotesHarm",
"SpamAbuse",
"Malware",
"Harassment",
];
const USER_REASONS: API.UserReportReason[] = [
"NoneSpecified",
"SpamAbuse",
"InappropriateProfile",
"Impersonation",
"BanEvasion",
"Underage",
];
/**
* Report creation modal
*/
export default function ReportContent({
target,
...props
}: ModalProps<"report">) {
const client = useClient();
return (
<ModalForm
{...props}
title={
target instanceof MessageInterface ? (
<Text id="app.special.modals.report.message" />
) : (
<Text
id="app.special.modals.report.by_name"
fields={{
name:
target instanceof User
? target.username
: target.name,
}}
/>
)
}
schema={{
selected: "custom",
reason: "combo",
additional_context: "text",
}}
data={{
selected: {
element:
target instanceof MessageInterface ? (
<Message message={target} head />
) : target instanceof User ? (
<Row centred>
<UserShort user={target} size={32} />
</Row>
) : (
<></>
),
},
reason: {
field: (
<Text id="app.special.modals.report.reason" />
) as React.ReactChild,
options: (target instanceof User
? USER_REASONS
: CONTENT_REASONS
).map((value) => ({
name: (
<Text
id={
value === "NoneSpecified"
? "app.special.modals.report.no_reason"
: `app.special.modals.report.${
target instanceof User
? "user"
: "content"
}_reason.${value}`
}
/>
),
value,
})),
},
additional_context: {
field: (
<Text id="app.special.modals.report.additional_context" />
) as React.ReactChild,
},
}}
callback={async ({ reason, additional_context }) => {
await client.api.post("/safety/report", {
content: {
id: target._id,
type:
target instanceof MessageInterface
? "Message"
: target instanceof User
? "User"
: "Server",
report_reason: reason as any,
},
additional_context,
});
}}
submit={{
children: <Text id="app.special.modals.actions.report" />,
}}
/>
);
}

View file

@ -28,16 +28,24 @@ export default function ServerInfo({
}
actions={[
{
onClick: () =>
onClick: () => {
modalController.push({
type: "server_identity",
member: server.member!,
}),
});
return true;
},
children: "Edit Identity",
palette: "primary",
},
{
onClick: () => report(server),
onClick: () => {
modalController.push({
type: "report",
target: server,
});
return true;
},
children: <Text id="app.special.modals.actions.report" />,
palette: "error",
},

View file

@ -179,6 +179,10 @@ export type Modal = {
| {
type: "import_theme";
}
| {
type: "report";
target: Server | User | Message;
}
);
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {

View file

@ -111,7 +111,8 @@ type Action =
action: "set_notification_state";
key: string;
state?: NotificationState;
};
}
| { action: "report"; target: User | Server | Message };
// ! FIXME: I dare someone to re-write this
// Tip: This should just be split into separate context menus per logical area.
@ -449,6 +450,12 @@ export default function ContextMenus() {
case "open_server_settings":
history.push(`/server/${data.id}/settings`);
break;
case "report":
modalController.push({
type: "report",
target: data.target,
});
break;
}
})().catch((err) => {
modalController.push({
@ -669,6 +676,19 @@ export default function ContextMenus() {
} as unknown as Action);
}
}
if (user._id !== userId) {
generateAction(
{
action: "report",
target: user,
},
"report_user",
undefined,
undefined,
"var(--error)",
);
}
}
if (contextualChannel) {
@ -795,14 +815,33 @@ export default function ContextMenus() {
});
}
if (message.author_id !== userId) {
generateAction(
{
action: "report",
target: message,
},
"report_message",
undefined,
undefined,
"var(--error)",
);
}
if (
message.author_id === userId ||
channelPermissions & Permission.ManageMessages
) {
generateAction({
action: "delete_message",
target: message,
});
generateAction(
{
action: "delete_message",
target: message,
},
undefined,
undefined,
undefined,
"var(--error)",
);
}
if (
@ -1035,6 +1074,17 @@ export default function ContextMenus() {
"var(--error)",
);
} else {
generateAction(
{
action: "report",
target: server,
},
"report_server",
undefined,
undefined,
"var(--error)",
);
generateAction(
{ action: "leave_server", target: server },
"leave_server",