Add a "NEW" Badge for New Plugins (V2)! (#234)
Co-authored-by: Ven <vendicated@riseup.net> Co-authored-by: Justice Almanzar <superdash993@gmail.com> Co-authored-by: ArjixWasTaken <53124886+ArjixWasTaken@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									074542f0b3
								
							
						
					
					
						commit
						aff1b68d6b
					
				
					 7 changed files with 87 additions and 9 deletions
				
			
		|  | @ -34,6 +34,7 @@ | |||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@types/diff": "^5.0.2", | ||||
|         "@types/lodash": "^4.14.0", | ||||
|         "@types/node": "^18.11.9", | ||||
|         "@types/react": "^18.0.25", | ||||
|         "@types/react-dom": "^18.0.9", | ||||
|  |  | |||
							
								
								
									
										6
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							|  | @ -10,6 +10,7 @@ patchedDependencies: | |||
| 
 | ||||
| specifiers: | ||||
|   '@types/diff': ^5.0.2 | ||||
|   '@types/lodash': ^4.14.0 | ||||
|   '@types/node': ^18.11.9 | ||||
|   '@types/react': ^18.0.25 | ||||
|   '@types/react-dom': ^18.0.9 | ||||
|  | @ -41,6 +42,7 @@ dependencies: | |||
| 
 | ||||
| devDependencies: | ||||
|   '@types/diff': 5.0.2 | ||||
|   '@types/lodash': 4.14.189 | ||||
|   '@types/node': 18.11.9 | ||||
|   '@types/react': 18.0.25 | ||||
|   '@types/react-dom': 18.0.9 | ||||
|  | @ -152,6 +154,10 @@ packages: | |||
|     resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} | ||||
|     dev: true | ||||
| 
 | ||||
|   /@types/lodash/4.14.189: | ||||
|     resolution: {integrity: sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==} | ||||
|     dev: true | ||||
| 
 | ||||
|   /@types/node/18.11.9: | ||||
|     resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} | ||||
|     dev: true | ||||
|  |  | |||
							
								
								
									
										30
									
								
								src/components/PluginSettings/components/BadgeComponent.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/components/PluginSettings/components/BadgeComponent.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| /* | ||||
|  * Vencord, a modification for Discord's desktop app | ||||
|  * Copyright (c) 2022 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/>.
 | ||||
| */ | ||||
| 
 | ||||
| import { BadgeStyle } from "@components/PluginSettings/styles"; | ||||
| 
 | ||||
| export function Badge({ text, color }): JSX.Element { | ||||
|     return ( | ||||
|         <div style={{ | ||||
|             backgroundColor: color, | ||||
|             justifySelf: "flex-end", | ||||
|             marginLeft: "auto", | ||||
|             ...BadgeStyle | ||||
|         }}>{text}</div> | ||||
|     ); | ||||
| } | ||||
|  | @ -29,6 +29,7 @@ export interface ISettingElementProps<T extends PluginOptionBase> { | |||
|     onError(hasError: boolean): void; | ||||
| } | ||||
| 
 | ||||
| export * from "./BadgeComponent"; | ||||
| export * from "./SettingBooleanComponent"; | ||||
| export * from "./SettingCustomComponent"; | ||||
| export * from "./SettingNumericComponent"; | ||||
|  |  | |||
|  | @ -16,26 +16,27 @@ | |||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| import * as DataStore from "@api/DataStore"; | ||||
| import { showNotice } from "@api/Notices"; | ||||
| import { Settings, useSettings } from "@api/settings"; | ||||
| import ErrorBoundary from "@components/ErrorBoundary"; | ||||
| import { ErrorCard } from "@components/ErrorCard"; | ||||
| import { Flex } from "@components/Flex"; | ||||
| import { handleComponentFailed } from "@components/handleComponentFailed"; | ||||
| import { Badge } from "@components/PluginSettings/components"; | ||||
| import PluginModal from "@components/PluginSettings/PluginModal"; | ||||
| import * as styles from "@components/PluginSettings/styles"; | ||||
| import { ChangeList } from "@utils/ChangeList"; | ||||
| import Logger from "@utils/Logger"; | ||||
| import { classes, LazyComponent } from "@utils/misc"; | ||||
| import { classes, LazyComponent, useAwaiter } from "@utils/misc"; | ||||
| import { openModalLazy } from "@utils/modal"; | ||||
| import { Plugin } from "@utils/types"; | ||||
| import { findByCode, findByPropsLazy } from "@webpack"; | ||||
| import { Alerts, Button, Forms, Margins, Parser, React, Select, Switch, Text, TextInput, Toasts, Tooltip } from "@webpack/common"; | ||||
| import { startDependenciesRecursive, startPlugin, stopPlugin } from "plugins"; | ||||
| 
 | ||||
| import Plugins from "~plugins"; | ||||
| 
 | ||||
| import { startDependenciesRecursive, startPlugin, stopPlugin } from "../../plugins"; | ||||
| import PluginModal from "./PluginModal"; | ||||
| import * as styles from "./styles"; | ||||
| 
 | ||||
| const logger = new Logger("PluginSettings", "#a6d189"); | ||||
| 
 | ||||
| const InputStyles = findByPropsLazy("inputDefault", "inputWrapper"); | ||||
|  | @ -78,9 +79,10 @@ interface PluginCardProps extends React.HTMLProps<HTMLDivElement> { | |||
|     plugin: Plugin; | ||||
|     disabled: boolean; | ||||
|     onRestartNeeded(name: string): void; | ||||
|     isNew?: boolean; | ||||
| } | ||||
| 
 | ||||
| function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLeave }: PluginCardProps) { | ||||
| function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLeave, isNew }: PluginCardProps) { | ||||
|     const settings = useSettings(); | ||||
|     const pluginSettings = settings.plugins[plugin.name]; | ||||
| 
 | ||||
|  | @ -162,8 +164,15 @@ function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLe | |||
|                 </Text>} | ||||
|                 hideBorder={true} | ||||
|             > | ||||
|                 <Flex style={{ marginTop: "auto", width: "100%", height: "100%", alignItems: "center" }}> | ||||
|                     <Text variant="text-md/bold" style={{ flexGrow: "1" }}>{plugin.name}</Text> | ||||
|                 <Flex style={{ marginTop: "auto", width: "100%", height: "100%", alignItems: "center", gap: "8px" }}> | ||||
|                     <Text | ||||
|                         variant="text-md/bold" | ||||
|                         style={{ | ||||
|                             display: "flex", width: "100%", alignItems: "center", flexGrow: "1", gap: "8px" | ||||
|                         }} | ||||
|                     > | ||||
|                         {plugin.name}{(isNew) && <Badge text="NEW" color="#ED4245" />} | ||||
|                     </Text> | ||||
|                     <button role="switch" onClick={() => openModal()} style={styles.SettingsIcon} className="button-12Fmur"> | ||||
|                         {plugin.options | ||||
|                             ? <CogWheel | ||||
|  | @ -243,6 +252,23 @@ export default ErrorBoundary.wrap(function Settings() { | |||
|         ); | ||||
|     }; | ||||
| 
 | ||||
|     const [newPlugins] = useAwaiter(() => DataStore.get("Vencord_existingPlugins").then((cachedPlugins: Record<string, number> | undefined) => { | ||||
|         const now = Date.now() / 1000; | ||||
|         const existingTimestamps: Record<string, number> = {}; | ||||
|         const sortedPluginNames = Object.values(sortedPlugins).map(plugin => plugin.name); | ||||
| 
 | ||||
|         const newPlugins: string[] = []; | ||||
|         for (const { name: p } of sortedPlugins) { | ||||
|             const time = existingTimestamps[p] = cachedPlugins?.[p] ?? now; | ||||
|             if ((time + 60 * 60 * 24 * 2) > now) { | ||||
|                 newPlugins.push(p); | ||||
|             } | ||||
|         } | ||||
|         DataStore.set("Vencord_existingPlugins", existingTimestamps); | ||||
| 
 | ||||
|         return window._.isEqual(newPlugins, sortedPluginNames) ? [] : newPlugins; | ||||
|     })); | ||||
| 
 | ||||
|     return ( | ||||
|         <Forms.FormSection> | ||||
|             <Forms.FormTitle tag="h5" className={classes(Margins.marginTop20, Margins.marginBottom8)}> | ||||
|  | @ -281,6 +307,7 @@ export default ErrorBoundary.wrap(function Settings() { | |||
|                             onRestartNeeded={name => changes.add(name)} | ||||
|                             disabled={plugin.required || !!dependency} | ||||
|                             plugin={plugin} | ||||
|                             isNew={newPlugins?.includes(plugin.name)} | ||||
|                             key={plugin.name} | ||||
|                         />; | ||||
|                     }) | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ export const PluginsGridItem: React.CSSProperties = { | |||
|     borderRadius: 3, | ||||
|     cursor: "pointer", | ||||
|     display: "block", | ||||
|     height: "min-content", | ||||
|     height: "100%", | ||||
|     padding: 10, | ||||
|     width: "100%", | ||||
| }; | ||||
|  | @ -48,3 +48,14 @@ export const SettingsIcon: React.CSSProperties = { | |||
|     background: "transparent", | ||||
|     marginRight: 8 | ||||
| }; | ||||
| 
 | ||||
| export const BadgeStyle: React.CSSProperties = { | ||||
|     padding: "0 6px", | ||||
|     fontFamily: "var(--font-display)", | ||||
|     fontWeight: "500", | ||||
|     borderRadius: "8px", | ||||
|     height: "16px", | ||||
|     fontSize: "12px", | ||||
|     lineHeight: "16px", | ||||
|     color: "var(--white-500)", | ||||
| }; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								src/globals.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/globals.d.ts
									
										
									
									
										vendored
									
									
								
							|  | @ -16,6 +16,7 @@ | |||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| import { LoDashStatic } from "lodash"; | ||||
| 
 | ||||
| declare global { | ||||
|     /** | ||||
|  | @ -54,6 +55,7 @@ declare global { | |||
|             push(chunk: any): any; | ||||
|             pop(): any; | ||||
|         }; | ||||
|         _: LoDashStatic; | ||||
|         [k: string]: any; | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue