ReviewDB: make warning review disableable; add timestamps (#948)
This commit is contained in:
		
							parent
							
								
									5b485806ea
								
							
						
					
					
						commit
						043381963b
					
				
					 7 changed files with 93 additions and 23 deletions
				
			
		|  | @ -19,6 +19,7 @@ | |||
| import { Settings } from "@api/settings"; | ||||
| 
 | ||||
| import { Review } from "../entities/Review"; | ||||
| import { ReviewDBUser } from "../entities/User"; | ||||
| import { authorize, showToast } from "./Utils"; | ||||
| 
 | ||||
| const API_URL = "https://manti.vendicated.dev"; | ||||
|  | @ -32,8 +33,12 @@ interface Response { | |||
|     updated: boolean; | ||||
| } | ||||
| 
 | ||||
| const WarningFlag = 0b00000010; | ||||
| 
 | ||||
| export async function getReviews(id: string): Promise<Review[]> { | ||||
|     const req = await fetch(API_URL + `/api/reviewdb/users/${id}/reviews`); | ||||
|     var flags = 0; | ||||
|     if (!Settings.plugins.ReviewDB.showWarning) flags |= WarningFlag; | ||||
|     const req = await fetch(API_URL + `/api/reviewdb/users/${id}/reviews?flags=${flags}`); | ||||
| 
 | ||||
|     const res = (req.status === 200) ? await req.json() as Response : { success: false, message: "An Error occured while fetching reviews. Please try again later.", reviews: [], updated: false }; | ||||
|     if (!res.success) { | ||||
|  | @ -43,6 +48,7 @@ export async function getReviews(id: string): Promise<Review[]> { | |||
|                 id: 0, | ||||
|                 comment: "An Error occured while fetching reviews. Please try again later.", | ||||
|                 star: 0, | ||||
|                 timestamp: 0, | ||||
|                 sender: { | ||||
|                     id: 0, | ||||
|                     username: "Error", | ||||
|  | @ -108,8 +114,10 @@ export async function reportReview(id: number) { | |||
|     showToast(await res.message); | ||||
| } | ||||
| 
 | ||||
| export function getLastReviewID(id: string): Promise<number> { | ||||
|     return fetch(API_URL + "/getLastReviewID?discordid=" + id) | ||||
|         .then(r => r.text()) | ||||
|         .then(Number); | ||||
| export function getCurrentUserInfo(token: string): Promise<ReviewDBUser> { | ||||
|     return fetch(API_URL + "/api/reviewdb/users", { | ||||
|         body: JSON.stringify({ token }), | ||||
|         method: "POST", | ||||
|     }) | ||||
|         .then(r => r.json()); | ||||
| } | ||||
|  |  | |||
|  | @ -17,13 +17,13 @@ | |||
| */ | ||||
| 
 | ||||
| import { Settings } from "@api/settings"; | ||||
| import { Devs } from "@utils/constants"; | ||||
| import Logger from "@utils/Logger"; | ||||
| import { openModal } from "@utils/modal"; | ||||
| import { findByProps } from "@webpack"; | ||||
| import { FluxDispatcher, React, SelectedChannelStore, Toasts, UserUtils } from "@webpack/common"; | ||||
| 
 | ||||
| import { Review } from "../entities/Review"; | ||||
| import { UserType } from "../entities/User"; | ||||
| 
 | ||||
| export async function openUserProfileModal(userId: string) { | ||||
|     await UserUtils.fetchUser(userId); | ||||
|  | @ -86,10 +86,5 @@ export function showToast(text: string) { | |||
| export const sleep = (ms: number) => new Promise(r => setTimeout(r, ms)); | ||||
| 
 | ||||
| export function canDeleteReview(review: Review, userId: string) { | ||||
|     if (review.sender.discordID === userId) return true; | ||||
| 
 | ||||
|     const myId = BigInt(userId); | ||||
|     return myId === Devs.mantikafasi.id || | ||||
|         myId === Devs.Ven.id || | ||||
|         myId === Devs.rushii.id; | ||||
|     if (review.sender.discordID === userId || Settings.plugins.ReviewDB.userType === UserType.Admin) return true; | ||||
| } | ||||
|  |  | |||
|  | @ -16,9 +16,10 @@ | |||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| import { Settings } from "@api/settings"; | ||||
| import { classes, LazyComponent } from "@utils/misc"; | ||||
| import { filters, findBulk } from "@webpack"; | ||||
| import { Alerts, UserStore } from "@webpack/common"; | ||||
| import { Alerts, moment, Timestamp, UserStore } from "@webpack/common"; | ||||
| 
 | ||||
| import { Review } from "../entities/Review"; | ||||
| import { deleteReview, reportReview } from "../Utils/ReviewDBAPI"; | ||||
|  | @ -32,7 +33,7 @@ export default LazyComponent(() => { | |||
|     const [ | ||||
|         { cozyMessage, buttons, message, groupStart }, | ||||
|         { container, isHeader }, | ||||
|         { avatar, clickable, username, messageContent, wrapper, cozy }, | ||||
|         { avatar, clickable, username, messageContent, wrapper, cozy, timestampInline, timestamp }, | ||||
|         { contents }, | ||||
|         buttonClasses, | ||||
|         { defaultColor } | ||||
|  | @ -102,6 +103,16 @@ export default LazyComponent(() => { | |||
|                         {review.sender.username} | ||||
|                     </span> | ||||
|                     {review.sender.badges.map(badge => <ReviewBadge {...badge} />)} | ||||
| 
 | ||||
|                     { | ||||
|                         !Settings.plugins.ReviewDB.hideTimestamps && ( | ||||
|                             <Timestamp | ||||
|                                 timestamp={moment(review.timestamp * 1000)} | ||||
|                                 compact={true} | ||||
|                             /> | ||||
|                         ) | ||||
|                     } | ||||
| 
 | ||||
|                     <p | ||||
|                         className={classes(messageContent, defaultColor)} | ||||
|                         style={{ fontSize: 15, marginTop: 4 }} | ||||
|  |  | |||
|  | @ -16,18 +16,20 @@ | |||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| import { Settings } from "@api/settings"; | ||||
| import { classes, useAwaiter } from "@utils/misc"; | ||||
| import { findLazy } from "@webpack"; | ||||
| import { Forms, React, Text, UserStore } from "@webpack/common"; | ||||
| import type { KeyboardEvent } from "react"; | ||||
| 
 | ||||
| import { addReview, getReviews } from "../Utils/ReviewDBAPI"; | ||||
| import { showToast } from "../Utils/Utils"; | ||||
| import { authorize, showToast } from "../Utils/Utils"; | ||||
| import ReviewComponent from "./ReviewComponent"; | ||||
| 
 | ||||
| const Classes = findLazy(m => typeof m.textarea === "string"); | ||||
| 
 | ||||
| export default function ReviewsView({ userId }: { userId: string; }) { | ||||
|     const { token } = Settings.plugins.ReviewDB; | ||||
|     const [refetchCount, setRefetchCount] = React.useState(0); | ||||
|     const [reviews, _, isLoading] = useAwaiter(() => getReviews(userId), { | ||||
|         fallbackValue: [], | ||||
|  | @ -83,8 +85,21 @@ export default function ReviewsView({ userId }: { userId: string; }) { | |||
|             <textarea | ||||
|                 className={classes(Classes.textarea.replace("textarea", ""), "enter-comment")} | ||||
|                 // this produces something like '-_59yqs ...' but since no class exists with that name its fine
 | ||||
|                 placeholder={reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id) ? `Update review for @${username}` : `Review @${username}`} | ||||
|                 placeholder={ | ||||
|                     token | ||||
|                         ? (reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id) | ||||
|                             ? `Update review for @${username}` | ||||
|                             : `Review @${username}`) | ||||
|                         : "You need to authorize to review users!" | ||||
|                 } | ||||
|                 onKeyDown={onKeyPress} | ||||
|                 onClick={() => { | ||||
|                     if (!token) { | ||||
|                         showToast("Opening authorization window..."); | ||||
|                         authorize(); | ||||
|                     } | ||||
|                 }} | ||||
| 
 | ||||
|                 style={{ | ||||
|                     marginTop: "6px", | ||||
|                     resize: "none", | ||||
|  |  | |||
|  | @ -31,4 +31,5 @@ export interface Review { | |||
|     id: number, | ||||
|     star: number, | ||||
|     sender: Sender, | ||||
|     timestamp: number | ||||
| } | ||||
|  |  | |||
							
								
								
									
										28
									
								
								src/plugins/reviewDB/entities/User.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/plugins/reviewDB/entities/User.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| /* | ||||
|  * Vencord, a modification for Discord's desktop app | ||||
|  * Copyright (c) 2023 Vendicated and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| export const enum UserType { | ||||
|     Banned = -1, | ||||
|     Normal = 0, | ||||
|     Admin = 1 | ||||
| } | ||||
| 
 | ||||
| export interface ReviewDBUser { | ||||
|     lastReviewID: number, | ||||
|     type: UserType; | ||||
| } | ||||
|  | @ -22,11 +22,11 @@ import { Settings } from "@api/settings"; | |||
| import ErrorBoundary from "@components/ErrorBoundary"; | ||||
| import { Devs } from "@utils/constants"; | ||||
| import definePlugin, { OptionType } from "@utils/types"; | ||||
| import { Button, UserStore } from "@webpack/common"; | ||||
| import { Button } from "@webpack/common"; | ||||
| import { User } from "discord-types/general"; | ||||
| 
 | ||||
| import ReviewsView from "./components/ReviewsView"; | ||||
| import { getLastReviewID } from "./Utils/ReviewDBAPI"; | ||||
| import { getCurrentUserInfo } from "./Utils/ReviewDBAPI"; | ||||
| import { authorize, showToast } from "./Utils/Utils"; | ||||
| 
 | ||||
| export default definePlugin({ | ||||
|  | @ -58,19 +58,31 @@ export default definePlugin({ | |||
|             type: OptionType.BOOLEAN, | ||||
|             description: "Notify about new reviews on startup", | ||||
|             default: true, | ||||
|         }, | ||||
|         showWarning: { | ||||
|             type: OptionType.BOOLEAN, | ||||
|             description: "Display warning to be respectful at the top of the reviews list", | ||||
|             default: true, | ||||
|         }, | ||||
|         hideTimestamps: { | ||||
|             type: OptionType.BOOLEAN, | ||||
|             description: "Hide timestamps on reviews", | ||||
|             default: false, | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     async start() { | ||||
|         const settings = Settings.plugins.ReviewDB; | ||||
|         if (!settings.lastReviewId || !settings.notifyReviews) return; | ||||
|         if (!settings.notifyReviews || !settings.token) return; | ||||
| 
 | ||||
|         setTimeout(async () => { | ||||
|             const id = await getLastReviewID(UserStore.getCurrentUser().id); | ||||
|             if (settings.lastReviewId < id) { | ||||
|                 showToast("You have new reviews on your profile!"); | ||||
|                 settings.lastReviewId = id; | ||||
|             const user = await getCurrentUserInfo(settings.token); | ||||
|             if (settings.lastReviewId < user.lastReviewID) { | ||||
|                 settings.lastReviewId = user.lastReviewID; | ||||
|                 if (user.lastReviewID !== 0) | ||||
|                     showToast("You have new reviews on your profile!"); | ||||
|             } | ||||
|             settings.userType = user.type; | ||||
|         }, 4000); | ||||
|     }, | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue