diff options
Diffstat (limited to 'src/plugins/reviewDB')
-rw-r--r-- | src/plugins/reviewDB/components/ReviewBadge.tsx | 4 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/ReviewComponent.tsx | 16 | ||||
-rw-r--r-- | src/plugins/reviewDB/components/ReviewsView.tsx | 119 | ||||
-rw-r--r-- | src/plugins/reviewDB/entities.ts | 15 | ||||
-rw-r--r-- | src/plugins/reviewDB/index.tsx | 65 | ||||
-rw-r--r-- | src/plugins/reviewDB/reviewDbApi.ts | 9 | ||||
-rw-r--r-- | src/plugins/reviewDB/style.css | 37 |
7 files changed, 171 insertions, 94 deletions
diff --git a/src/plugins/reviewDB/components/ReviewBadge.tsx b/src/plugins/reviewDB/components/ReviewBadge.tsx index e65dff2..3c02c35 100644 --- a/src/plugins/reviewDB/components/ReviewBadge.tsx +++ b/src/plugins/reviewDB/components/ReviewBadge.tsx @@ -28,8 +28,8 @@ export default function ReviewBadge(badge: Badge) { {({ onMouseEnter, onMouseLeave }) => ( <img className={cl("badge")} - width="24px" - height="24px" + width="22px" + height="22px" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} src={badge.icon} diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx index fa4cad4..1278a50 100644 --- a/src/plugins/reviewDB/components/ReviewComponent.tsx +++ b/src/plugins/reviewDB/components/ReviewComponent.tsx @@ -20,7 +20,7 @@ import { openUserProfile } from "@utils/discord"; import { classes } from "@utils/misc"; import { LazyComponent } from "@utils/react"; import { filters, findBulk } from "@webpack"; -import { Alerts, moment, Timestamp, UserStore } from "@webpack/common"; +import { Alerts, moment, Parser, Timestamp, UserStore } from "@webpack/common"; import { Review, ReviewType } from "../entities"; import { deleteReview, reportReview } from "../reviewDbApi"; @@ -30,12 +30,12 @@ import { DeleteButton, ReportButton } from "./MessageButton"; import ReviewBadge from "./ReviewBadge"; export default LazyComponent(() => { - // this is terrible, blame mantika + // this is terrible, blame ven const p = filters.byProps; const [ { cozyMessage, buttons, message, buttonsInner, groupStart }, { container, isHeader }, - { avatar, clickable, username, messageContent, wrapper, cozy }, + { avatar, clickable, username, wrapper, cozy }, buttonClasses, botTag ] = findBulk( @@ -124,12 +124,10 @@ export default LazyComponent(() => { </Timestamp>) } - <p - className={classes(messageContent)} - style={{ fontSize: 15, marginTop: 4, color: "var(--text-normal)" }} - > - {review.comment} - </p> + <div className={cl("review-comment")}> + {Parser.parseGuildEventDescription(review.comment)} + </div> + {review.id !== 0 && ( <div className={classes(container, isHeader, buttons)} style={{ padding: "0px", diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx index ada0fa0..e5bc426 100644 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ b/src/plugins/reviewDB/components/ReviewsView.tsx @@ -16,11 +16,9 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { classes } from "@utils/misc"; -import { useAwaiter, useForceUpdater } from "@utils/react"; -import { findByPropsLazy } from "@webpack"; -import { Forms, React, RelationshipStore, UserStore } from "@webpack/common"; -import type { KeyboardEvent } from "react"; +import { LazyComponent, useAwaiter, useForceUpdater } from "@utils/react"; +import { find, findByPropsLazy } from "@webpack"; +import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common"; import { Review } from "../entities"; import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "../reviewDbApi"; @@ -28,7 +26,12 @@ import { settings } from "../settings"; import { authorize, cl, showToast } from "../utils"; import ReviewComponent from "./ReviewComponent"; -const Classes = findByPropsLazy("inputDefault", "editable"); + +const Editor = findByPropsLazy("start", "end", "addMark"); +const Transform = findByPropsLazy("unwrapNodes"); +const InputTypes = findByPropsLazy("VOICE_CHANNEL_STATUS", "SIDEBAR"); + +const InputComponent = LazyComponent(() => find(m => m?.type?.render?.toString().includes("CHANNEL_TEXT_AREA).AnalyticsLocationProvider"))); interface UserProps { discordId: string; @@ -113,48 +116,82 @@ function ReviewList({ refetch, reviews, hideOwnReview }: { refetch(): void; revi ); } + export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: { discordId: string, name: string; isAuthor: boolean; refetch(): void; }) { const { token } = settings.store; - - function onKeyPress({ key, target }: KeyboardEvent<HTMLTextAreaElement>) { - if (key === "Enter") { - addReview({ - userid: discordId, - comment: (target as HTMLInputElement).value, - star: -1 - }).then(res => { - if (res?.success) { - (target as HTMLInputElement).value = ""; // clear the input - refetch(); - } else if (res?.message) { - showToast(res.message); - } - }); - } - } + const editorRef = useRef<any>(null); + const inputType = InputTypes.FORM; + inputType.disableAutoFocus = true; + + const channel = { + flags_: 256, + guild_id_: null, + id: "0", + getGuildId: () => null, + isPrivate: () => true, + isActiveThread: () => false, + isArchivedLockedThread: () => false, + isDM: () => true, + roles: { "0": { permissions: 0n } }, + getRecipientId: () => "0", + hasFlag: () => false, + }; return ( - <textarea - className={classes(Classes.inputDefault, "enter-comment", cl("input"))} - onKeyDownCapture={e => { - if (e.key === "Enter") { - e.preventDefault(); // prevent newlines - } - }} - placeholder={ - !token - ? "You need to authorize to review users!" - : isAuthor - ? `Update review for @${name}` - : `Review @${name}` - } - onKeyDown={onKeyPress} - onClick={() => { + <> + <div onClick={() => { if (!token) { showToast("Opening authorization window..."); authorize(); } - }} - /> + }}> + <InputComponent + className={cl("input")} + channel={channel} + placeholder={ + !token + ? "You need to authorize to review users!" + : isAuthor + ? `Update review for @${name}` + : `Review @${name}` + } + type={inputType} + disableThemedBackground={true} + setEditorRef={ref => editorRef.current = ref} + textValue="" + onSubmit={ + async res => { + const response = await addReview({ + userid: discordId, + comment: res.value, + }); + + if (response?.success) { + refetch(); + + const slateEditor = editorRef.current.ref.current.getSlateEditor(); + + // clear editor + Transform.delete(slateEditor, { + at: { + anchor: Editor.start(slateEditor, []), + focus: Editor.end(slateEditor, []), + } + }); + } else if (response?.message) { + showToast(response.message); + } + + // even tho we need to return this, it doesnt do anything + return { + shouldClear: false, + shouldRefocus: true, + }; + } + } + /> + </div> + + </> ); } diff --git a/src/plugins/reviewDB/entities.ts b/src/plugins/reviewDB/entities.ts index 1415101..fefb1d3 100644 --- a/src/plugins/reviewDB/entities.ts +++ b/src/plugins/reviewDB/entities.ts @@ -29,6 +29,13 @@ export const enum ReviewType { System = 3 } +export const enum NotificationType { + Info = 0, + Ban = 1, + Unban = 2, + Warning = 3 +} + export interface Badge { name: string; description: string; @@ -45,6 +52,13 @@ export interface BanInfo { banEndDate: number; } +export interface Notification { + id: number; + title: string; + content: string; + type: NotificationType; +} + export interface ReviewDBUser { ID: number; discordID: string; @@ -54,6 +68,7 @@ export interface ReviewDBUser { warningCount: number; badges: any[]; banInfo: BanInfo | null; + notification: Notification | null; lastReviewID: number; type: UserType; } diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index de09ac7..a519713 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -24,13 +24,13 @@ import ExpandableHeader from "@components/ExpandableHeader"; import { OpenExternalIcon } from "@components/Icons"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { Alerts, Menu, useState } from "@webpack/common"; +import { Alerts, Menu, Parser, useState } from "@webpack/common"; import { Guild, User } from "discord-types/general"; import { openReviewsModal } from "./components/ReviewModal"; import ReviewsView from "./components/ReviewsView"; -import { UserType } from "./entities"; -import { getCurrentUserInfo } from "./reviewDbApi"; +import { NotificationType } from "./entities"; +import { getCurrentUserInfo, readNotification } from "./reviewDbApi"; import { settings } from "./settings"; import { showToast } from "./utils"; @@ -78,40 +78,33 @@ export default definePlugin({ addContextMenuPatch("guild-header-popout", guildPopoutPatch); - if (user.banInfo) { - const endDate = new Date(user.banInfo.banEndDate); - if (endDate.getTime() > Date.now() && (s.user?.banInfo?.banEndDate ?? 0) < endDate.getTime()) { - Alerts.show({ - title: "You have been banned from ReviewDB", - body: ( - <> - <p> - You are banned from ReviewDB { - user.type === UserType.Banned - ? "permanently" - : "until " + endDate.toLocaleString() - } - </p> - {user.banInfo.reviewContent && ( - <p>Offending Review: {user.banInfo.reviewContent}</p> - )} - <p>Continued offenses will result in a permanent ban.</p> - </> - ), - cancelText: "Appeal", - confirmText: "Ok", - onCancel: () => - VencordNative.native.openExternal( - "https://reviewdb.mantikafasi.dev/api/redirect?" - + new URLSearchParams({ - token: settings.store.token!, - page: "dashboard/appeal" - }) - ) - }); - } + if (user.notification) { + const props = user.notification.type === NotificationType.Ban ? { + cancelText: "Appeal", + confirmText: "Ok", + onCancel: () => + VencordNative.native.openExternal( + "https://reviewdb.mantikafasi.dev/api/redirect?" + + new URLSearchParams({ + token: settings.store.token!, + page: "dashboard/appeal" + }) + ) + } : {}; + + Alerts.show({ + title: user.notification.title, + body: ( + Parser.parse( + user.notification.content, + false + ) + ), + ...props + }); + + readNotification(user.notification.id); } - s.user = user; }, 4000); }, diff --git a/src/plugins/reviewDB/reviewDbApi.ts b/src/plugins/reviewDB/reviewDbApi.ts index e8008c8..5370a9b 100644 --- a/src/plugins/reviewDB/reviewDbApi.ts +++ b/src/plugins/reviewDB/reviewDbApi.ts @@ -140,3 +140,12 @@ export function getCurrentUserInfo(token: string): Promise<ReviewDBUser> { method: "POST", }).then(r => r.json()); } + +export function readNotification(id: number) { + return fetch(API_URL + `/api/reviewdb/notifications?id=${id}`, { + method: "PATCH", + headers: { + "Authorization": settings.store.token || "", + }, + }); +} diff --git a/src/plugins/reviewDB/style.css b/src/plugins/reviewDB/style.css index 83cf087..f4d890f 100644 --- a/src/plugins/reviewDB/style.css +++ b/src/plugins/reviewDB/style.css @@ -14,7 +14,16 @@ overflow: hidden; background: transparent; border: 1px solid var(--profile-message-input-border-color); - font-size: 14px; +} + +.vc-rdb-modal-footer > div { + width: 100%; + margin: 6px 16px; +} + +/* When input becomes disabled(while sending review), input adds unneccesary padding to left, this prevents it */ +.vc-rdb-input > div > div { + padding-left: 0 !important; } .vc-rdb-placeholder { @@ -24,13 +33,12 @@ color: var(--text-muted); } -.vc-rdb-modal-footer { - padding: 0; +.vc-rdb-input * { + font-size: 14px; } -.vc-rdb-modal-footer > div { - width: 100%; - margin: 6px 16px; +.vc-rdb-modal-footer { + padding: 0; } .vc-rdb-modal-footer .vc-rdb-input { @@ -49,3 +57,20 @@ .vc-rdb-modal-reviews { margin-top: 16px; } + +.vc-rdb-review { + margin-top: 8px; + margin-bottom: 8px; +} + +.vc-rdb-review-comment img { + vertical-align: text-top; +} + +.vc-rdb-review-comment { + overflow-y: hidden; + margin-top: 1px; + margin-bottom: 8px; + color: var(--text-normal); + font-size: 15px; +} |