diff options
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | pnpm-lock.yaml | 6 | ||||
-rw-r--r-- | src/components/PluginSettings/components/BadgeComponent.tsx | 30 | ||||
-rw-r--r-- | src/components/PluginSettings/components/index.ts | 1 | ||||
-rw-r--r-- | src/components/PluginSettings/index.tsx | 43 | ||||
-rw-r--r-- | src/components/PluginSettings/styles.ts | 13 | ||||
-rw-r--r-- | src/globals.d.ts | 2 |
7 files changed, 87 insertions, 9 deletions
diff --git a/package.json b/package.json index fe83c6a..35c4aaf 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bca41ba..02c2ea6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/src/components/PluginSettings/components/BadgeComponent.tsx b/src/components/PluginSettings/components/BadgeComponent.tsx new file mode 100644 index 0000000..059376f --- /dev/null +++ b/src/components/PluginSettings/components/BadgeComponent.tsx @@ -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> + ); +} diff --git a/src/components/PluginSettings/components/index.ts b/src/components/PluginSettings/components/index.ts index 9e75068..d44fb38 100644 --- a/src/components/PluginSettings/components/index.ts +++ b/src/components/PluginSettings/components/index.ts @@ -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"; diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 5ee9cc9..93bb489 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -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} />; }) diff --git a/src/components/PluginSettings/styles.ts b/src/components/PluginSettings/styles.ts index 703c579..5621b76 100644 --- a/src/components/PluginSettings/styles.ts +++ b/src/components/PluginSettings/styles.ts @@ -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)", +}; diff --git a/src/globals.d.ts b/src/globals.d.ts index 069cbcb..2e8d444 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -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; } } |