From b6304635e710916908a2a2ab34feca7d8a78cc11 Mon Sep 17 00:00:00 2001 From: Rosie Val Date: Sun, 9 Aug 2026 14:52:34 -0400 Subject: [PATCH] Address PR review comments --- .../BrowseFilterAndSortActionSheet.tsx | 21 --------- .../components/BrowsePluginActionSheet.tsx | 43 +++++++++++++++++-- .../components/PluginCard.tsx | 9 +++- .../components/PluginList.tsx | 12 +++++- .../components/PluginOptionsActionSheet.tsx | 6 +-- ...tsx => PluginRelationsListActionSheet.tsx} | 7 ++- .../RepoRemoveConfirmationAlert.tsx | 3 +- src/plugins/start/settings.plugins/repos.ts | 13 ++++-- .../RevengePluginsAdvancedSettingScreen.tsx | 18 +++++--- .../RevengePluginsBrowseSettingScreen.tsx | 35 ++++++++------- .../start/settings.plugins/utils/alerts.tsx | 2 +- 11 files changed, 105 insertions(+), 64 deletions(-) rename src/plugins/start/settings.plugins/components/{PluginListActionSheet.tsx => PluginRelationsListActionSheet.tsx} (85%) diff --git a/src/plugins/start/settings.plugins/components/BrowseFilterAndSortActionSheet.tsx b/src/plugins/start/settings.plugins/components/BrowseFilterAndSortActionSheet.tsx index 208f9c6..7ceed9f 100644 --- a/src/plugins/start/settings.plugins/components/BrowseFilterAndSortActionSheet.tsx +++ b/src/plugins/start/settings.plugins/components/BrowseFilterAndSortActionSheet.tsx @@ -32,11 +32,6 @@ export interface BrowseFilterAndSortActionSheetProps { /** Checked repository URLs. */ checked: string[] setChecked: (urls: string[]) => void - /** Available release channels across all listings. */ - channels: string[] - /** Selected release channel. Empty string means default. */ - channel: string - setChannel: (channel: string) => void sort: BrowseSortKey setSort: (sort: BrowseSortKey) => void reverse: boolean @@ -47,9 +42,6 @@ export default function BrowseFilterAndSortActionSheet({ repos, checked, setChecked, - channels, - channel, - setChannel, sort, setSort, reverse, @@ -84,19 +76,6 @@ export default function BrowseFilterAndSortActionSheet({ ) })} - setChannel(v as string)} - > - - {channels.map(c => ( - - ))} - void + onInstall: (channel?: string, version?: string) => void sheetKey: string } @@ -31,17 +42,26 @@ export default function BrowsePluginActionSheet({ version, icon, id, + listing, + channel, repositoryText, onInstall, sheetKey, }: BrowsePluginActionSheetProps) { + const [selectedChannel, setSelectedChannel] = useState(channel) + const selectedVersion = selectedChannel + ? (listing.channels[selectedChannel] ?? '') + : version + + const channelNames = Object.keys(listing.channels) + return ( } /> + {channelNames.length > 0 && ( + setSelectedChannel(v as string)} + > + {channelNames.map(c => ( + + ))} + + )} diff --git a/src/plugins/start/settings.plugins/components/PluginCard.tsx b/src/plugins/start/settings.plugins/components/PluginCard.tsx index c593dd3..a079d9c 100644 --- a/src/plugins/start/settings.plugins/components/PluginCard.tsx +++ b/src/plugins/start/settings.plugins/components/PluginCard.tsx @@ -27,6 +27,7 @@ import { useEssentialPluginTooltip, } from './TooltipProvider' import type { AnyPlugin, InternalPluginMeta } from '@revenge-mod/plugins/_' +import type { RepoPluginListing } from '@revenge-mod/plugins/_/repositories' const { Card, Text, Stack, IconButton, Button, createStyles } = Design @@ -262,6 +263,8 @@ export const BrowsePluginCard = memo(function BrowsePluginCard({ author, icon, id, + listing, + channel, repositoryText, onInstall, }: { @@ -271,8 +274,10 @@ export const BrowsePluginCard = memo(function BrowsePluginCard({ author: string icon?: string id: string + listing: RepoPluginListing + channel: string repositoryText: string - onInstall: () => void + onInstall: (channel?: string, version?: string) => void }) { return ( void + onInstall: ( + entry: BrowseEntry, + channel?: string, + version?: string, + ) => void }) { const numColumns = useNumColumns() const resetTooltips = useResetTooltips() @@ -152,8 +156,12 @@ export function BrowsePluginMasonryFlashList({ author={listing.author} icon={listing.icon ?? undefined} id={listing.id} + listing={listing} + channel={entry.channel ?? ''} repositoryText={entry.repositoryText} - onInstall={() => onInstall(entry)} + onInstall={(channel, version) => + onInstall(entry, channel, version) + } /> ) }} diff --git a/src/plugins/start/settings.plugins/components/PluginOptionsActionSheet.tsx b/src/plugins/start/settings.plugins/components/PluginOptionsActionSheet.tsx index 0459dcb..a062f24 100644 --- a/src/plugins/start/settings.plugins/components/PluginOptionsActionSheet.tsx +++ b/src/plugins/start/settings.plugins/components/PluginOptionsActionSheet.tsx @@ -179,12 +179,11 @@ function AdvancedSection({ plugin }: { plugin: AnyPlugin }) { subLabel={`${name} depends on ${dependencies.length} other plugins`} onPress={() => { ActionSheetActionCreators.openLazy( - import('./PluginListActionSheet'), + import('./PluginRelationsListActionSheet'), `plugin-deps-${id}`, { title: `Dependencies of ${name}`, plugins: dependencies, - sheetKey: `plugin-deps-${id}`, }, ) }} @@ -197,12 +196,11 @@ function AdvancedSection({ plugin }: { plugin: AnyPlugin }) { subLabel={`${dependents.length} other plugins depend on ${name}`} onPress={() => { ActionSheetActionCreators.openLazy( - import('./PluginListActionSheet'), + import('./PluginRelationsListActionSheet'), `plugin-dependents-${id}`, { title: `Dependents of ${name}`, plugins: dependents, - sheetKey: `plugin-dependents-${id}`, }, ) }} diff --git a/src/plugins/start/settings.plugins/components/PluginListActionSheet.tsx b/src/plugins/start/settings.plugins/components/PluginRelationsListActionSheet.tsx similarity index 85% rename from src/plugins/start/settings.plugins/components/PluginListActionSheet.tsx rename to src/plugins/start/settings.plugins/components/PluginRelationsListActionSheet.tsx index f25b3eb..c39926b 100644 --- a/src/plugins/start/settings.plugins/components/PluginListActionSheet.tsx +++ b/src/plugins/start/settings.plugins/components/PluginRelationsListActionSheet.tsx @@ -4,16 +4,15 @@ import type { AnyPlugin } from '@revenge-mod/plugins/_' const { ActionSheet, Stack, TableRow, TableRowGroup } = Design -export interface PluginListActionSheetProps { +export interface PluginRelationsListActionSheetProps { title: string plugins: AnyPlugin[] - sheetKey: string } -export default function PluginListActionSheet({ +export default function PluginRelationsListActionSheet({ title, plugins, -}: PluginListActionSheetProps) { +}: PluginRelationsListActionSheetProps) { return ( diff --git a/src/plugins/start/settings.plugins/components/RepoRemoveConfirmationAlert.tsx b/src/plugins/start/settings.plugins/components/RepoRemoveConfirmationAlert.tsx index d9c8aa0..1f7b468 100644 --- a/src/plugins/start/settings.plugins/components/RepoRemoveConfirmationAlert.tsx +++ b/src/plugins/start/settings.plugins/components/RepoRemoveConfirmationAlert.tsx @@ -18,8 +18,7 @@ export default function RepoRemoveConfirmationAlert({ {repo.name ?? repo.url} {' '} - will be removed. You can restore the default repositories by - clearing Plugin Settings data. + will be removed. } actions={ diff --git a/src/plugins/start/settings.plugins/repos.ts b/src/plugins/start/settings.plugins/repos.ts index a9315bd..2972cd0 100644 --- a/src/plugins/start/settings.plugins/repos.ts +++ b/src/plugins/start/settings.plugins/repos.ts @@ -7,14 +7,16 @@ import { noop } from '@revenge-mod/utils/callback' import { api } from '.' import type { Repo, RepoConfigEntry } from '@revenge-mod/plugins/_/repositories' -export async function addDefaultRepoIfNeeded() { - if (!__BUILD_DEFAULT_PLUGIN_REPOSITORY_URL__) return +export async function addDefaultRepoIfNeeded( + refresh = false, +): Promise { + if (!__BUILD_DEFAULT_PLUGIN_REPOSITORY_URL__) return false const repos = await listRepos() if ( repos.some(repo => repo.url === __BUILD_DEFAULT_PLUGIN_REPOSITORY_URL__) ) - return + return false const userRepos = toConfig(repos.filter(repo => !repo.internal)) await setRepos([ @@ -24,7 +26,10 @@ export async function addDefaultRepoIfNeeded() { await api.jsonStorage.set({ defaultRepoRestored: true }).catch(noop) - await refreshRepo(__BUILD_DEFAULT_PLUGIN_REPOSITORY_URL__).catch(noop) + if (refresh) + await refreshRepo(__BUILD_DEFAULT_PLUGIN_REPOSITORY_URL__).catch(noop) + + return true } export function toConfig(list: Repo[]): RepoConfigEntry[] { diff --git a/src/plugins/start/settings.plugins/screens/RevengePluginsAdvancedSettingScreen.tsx b/src/plugins/start/settings.plugins/screens/RevengePluginsAdvancedSettingScreen.tsx index e8fe8f7..7e1415d 100644 --- a/src/plugins/start/settings.plugins/screens/RevengePluginsAdvancedSettingScreen.tsx +++ b/src/plugins/start/settings.plugins/screens/RevengePluginsAdvancedSettingScreen.tsx @@ -3,6 +3,7 @@ import { FormSwitch } from '@revenge-mod/components' import { styles } from '@revenge-mod/components/_' import Page from '@revenge-mod/components/Page' import TableRowAssetIcon from '@revenge-mod/components/TableRowAssetIcon' +import { ToastActionCreators } from '@revenge-mod/discord/actions' import { Design } from '@revenge-mod/discord/design' import { Clipboard } from '@revenge-mod/externals/react-native-clipboard' import { callNativeMethod } from '@revenge-mod/modules/native' @@ -373,11 +374,18 @@ export default function RevengePluginsAdvancedSettingScreen() { } label="Restore default repositories" - subLabel="Add the bundled default repository if it's missing" - onPress={() => { - addDefaultRepoIfNeeded().catch(e => - showErrorToast(messageOf(e)), - ) + onPress={async () => { + try { + const restored = + await addDefaultRepoIfNeeded(true) + if (!restored) + ToastActionCreators.open({ + key: 'revenge-default-repo-nothing', + content: 'No default repository to restore', + }) + } catch (e) { + showErrorToast(messageOf(e)) + } }} /> diff --git a/src/plugins/start/settings.plugins/screens/RevengePluginsBrowseSettingScreen.tsx b/src/plugins/start/settings.plugins/screens/RevengePluginsBrowseSettingScreen.tsx index c6096a0..d638a04 100644 --- a/src/plugins/start/settings.plugins/screens/RevengePluginsBrowseSettingScreen.tsx +++ b/src/plugins/start/settings.plugins/screens/RevengePluginsBrowseSettingScreen.tsx @@ -82,18 +82,15 @@ function Screen() { const [excluded, setExcluded] = useState([]) const [sort, setSort] = useState('name') const [reverse, setReverse] = useState(false) - const [channel, setChannel] = useState('') - const [channels, setChannels] = useState([]) const hasFilter = useMemo( - () => excluded.length > 0 || sort !== 'name' || reverse || channel !== '', - [excluded, sort, reverse, channel], + () => excluded.length > 0 || sort !== 'name' || reverse, + [excluded, sort, reverse], ) const load = useCallback(async () => { const repos = await listRepos() const all: BrowseEntry[] = [] - const allChannels = new Set() setInternalRepos( repos.filter(repo => repo.internal).map(repo => repo.url), @@ -111,9 +108,7 @@ function Screen() { for (const listing of listings) { const plugin = pList.get(listing.id) - for (const c of Object.keys(listing.channels)) - allChannels.add(c) - const displayChannel = displayChannelOf(listing, channel) + const displayChannel = displayChannelOf(listing, '') const displayVersion = displayChannel ? (listing.channels[displayChannel] ?? '') : '' @@ -143,9 +138,8 @@ function Screen() { ), ) - setChannels([...allChannels].sort()) setEntries(all) - }, [channel, setChannels]) + }, []) useEffect(() => { // Show cached indexes right away, then refresh everything @@ -167,12 +161,24 @@ function Screen() { }, [load]) const install = useCallback( - async (entry: BrowseEntry) => { + async ( + entry: BrowseEntry, + channel?: string, + version?: string, + ) => { + const targetChannel = channel || entry.channel + const targetVersion = + version || + (targetChannel + ? (entry.listing.channels[targetChannel] ?? '') + : '') || + entry.version + // Pin the displayed version, channel, and repository, so the plan matches the card await runInstallFlow( entry.listing.id, - entry.version || undefined, - entry.channel, + targetVersion || undefined, + targetChannel, // Internal repos so external plugins can link against internal plugins as well [...internalRepos, entry.repoUrl], ) @@ -239,9 +245,6 @@ function Screen() { .map(repo => repo.url) .filter(url => !urls.includes(url)), ), - channels, - channel, - setChannel, sort, setSort, reverse, diff --git a/src/plugins/start/settings.plugins/utils/alerts.tsx b/src/plugins/start/settings.plugins/utils/alerts.tsx index 7e07c66..88aa030 100644 --- a/src/plugins/start/settings.plugins/utils/alerts.tsx +++ b/src/plugins/start/settings.plugins/utils/alerts.tsx @@ -11,7 +11,7 @@ import PluginClearDataConfirmationAlert from '../components/PluginClearDataConfi import PluginHasDependenciesAlert from '../components/PluginHasDependenciesAlert' import PluginHasDependentsAlert from '../components/PluginHasDependentsAlert' import PluginMissingDependenciesAlert from '../components/PluginMissingDependenciesAlert' -import PluginStatesProvider from '../components/PluginStatesProvider' +import PluginStatesProvider from '../components/PluginStateProvider' import PluginUninstallConfirmationAlert from '../components/PluginUninstallConfirmationAlert' import RepoRemoveConfirmationAlert from '../components/RepoRemoveConfirmationAlert' import type { Repo } from '@revenge-mod/plugins/_/repositories'