mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-23 22:22:07 -05:00
feat: add reporting UI
This commit is contained in:
parent
46eec5a132
commit
7d544c82ab
6 changed files with 198 additions and 9 deletions
2
external/lang
vendored
2
external/lang
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 5bf84e27074daeab3055f299e54be955aae5042d
|
||||
Subproject commit 79d9b042866d466f39e3f4d053833416137491f8
|
|
@ -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,
|
||||
});
|
||||
|
|
125
src/controllers/modals/components/Report.tsx
Normal file
125
src/controllers/modals/components/Report.tsx
Normal 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" />,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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 } & {
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue