Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e444cf55d |
3 changed files with 117 additions and 118 deletions
|
|
@ -499,6 +499,7 @@ export namespace DiscordModules {
|
||||||
extends TableRowGroupProps {
|
extends TableRowGroupProps {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
onChange: (value: T) => void
|
onChange: (value: T) => void
|
||||||
|
value?: T
|
||||||
defaultValue?: T
|
defaultValue?: T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import {
|
||||||
} from '@revenge-mod/plugins/_'
|
} from '@revenge-mod/plugins/_'
|
||||||
import {
|
import {
|
||||||
listRepoPlugins,
|
listRepoPlugins,
|
||||||
listRepos,
|
|
||||||
refreshRepo,
|
refreshRepo,
|
||||||
} from '@revenge-mod/plugins/_/repositories'
|
} from '@revenge-mod/plugins/_/repositories'
|
||||||
import { PluginStatus } from '@revenge-mod/plugins/constants'
|
import { PluginStatus } from '@revenge-mod/plugins/constants'
|
||||||
|
|
@ -39,7 +38,11 @@ import {
|
||||||
showPluginClearDataConfirmation,
|
showPluginClearDataConfirmation,
|
||||||
showPluginUninstallConfirmation,
|
showPluginUninstallConfirmation,
|
||||||
} from '../utils/alerts'
|
} from '../utils/alerts'
|
||||||
import { messageOf, runInstallFlow, showErrorToast } from '../utils/repos'
|
import {
|
||||||
|
messageOf,
|
||||||
|
runInstallFlowWithInternalRepos,
|
||||||
|
showErrorToast,
|
||||||
|
} from '../utils/repos'
|
||||||
import { InstalledPluginSwitch, PluginInfo } from './PluginCard'
|
import { InstalledPluginSwitch, PluginInfo } from './PluginCard'
|
||||||
import { usePluginEnabled, usePluginStatus } from './PluginStateProvider'
|
import { usePluginEnabled, usePluginStatus } from './PluginStateProvider'
|
||||||
import PluginTooltipsProvider, {
|
import PluginTooltipsProvider, {
|
||||||
|
|
@ -47,7 +50,6 @@ import PluginTooltipsProvider, {
|
||||||
usePluginTooltip,
|
usePluginTooltip,
|
||||||
} from './TooltipProvider'
|
} from './TooltipProvider'
|
||||||
import type { AnyPlugin } from '@revenge-mod/plugins/_'
|
import type { AnyPlugin } from '@revenge-mod/plugins/_'
|
||||||
import type { RepoPluginListing } from '@revenge-mod/plugins/_/repositories'
|
|
||||||
|
|
||||||
export interface PluginOptionsActionSheetProps {
|
export interface PluginOptionsActionSheetProps {
|
||||||
plugin: AnyPlugin
|
plugin: AnyPlugin
|
||||||
|
|
@ -131,7 +133,8 @@ function PluginOptions({ plugin, sheetKey }: PluginOptionsActionSheetProps) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<StatusSection plugin={plugin} />
|
<StatusSection plugin={plugin} />
|
||||||
<AdvancedSection plugin={plugin} sheetKey={sheetKey} />
|
<ChannelSection plugin={plugin} />
|
||||||
|
<AdvancedSection plugin={plugin} />
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -173,92 +176,72 @@ function StatusSection({ plugin }: { plugin: AnyPlugin }) {
|
||||||
|
|
||||||
function ChannelSection({
|
function ChannelSection({
|
||||||
plugin,
|
plugin,
|
||||||
sheetKey,
|
|
||||||
}: {
|
}: {
|
||||||
plugin: AnyPlugin
|
plugin: AnyPlugin
|
||||||
sheetKey: string
|
|
||||||
}) {
|
}) {
|
||||||
const meta = getInternalPluginMeta(plugin)
|
const meta = getInternalPluginMeta(plugin)
|
||||||
const source = meta.source
|
const source = meta.source
|
||||||
if (isPluginInternal(meta) || !source?.repo) return null
|
if (isPluginInternal(meta) || !source?.repo) return null
|
||||||
|
|
||||||
const [listing, setListing] = useState<RepoPluginListing | null>(null)
|
const [channels, setChannels] = useState<Record<string, string>>({})
|
||||||
const [resetKey, setResetKey] = useState(0)
|
const [selected, setSelected] = useState(source.channel)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false
|
listRepoPlugins(source.repo)
|
||||||
;(async () => {
|
.then(listings => {
|
||||||
try {
|
const listing = listings.find(l => l.id === plugin.manifest.id)
|
||||||
const listings = await listRepoPlugins(source.repo)
|
if (listing) setChannels(listing.channels)
|
||||||
const found = listings.find(l => l.id === plugin.manifest.id)
|
})
|
||||||
if (found && !cancelled) setListing(found)
|
.catch(() =>
|
||||||
} catch {
|
refreshRepo(source.repo)
|
||||||
try {
|
.then(() => listRepoPlugins(source.repo))
|
||||||
await refreshRepo(source.repo)
|
.then(listings => {
|
||||||
const listings = await listRepoPlugins(source.repo)
|
const listing = listings.find(
|
||||||
const found = listings.find(l => l.id === plugin.manifest.id)
|
l => l.id === plugin.manifest.id,
|
||||||
if (found && !cancelled) setListing(found)
|
)
|
||||||
} catch {}
|
if (listing) setChannels(listing.channels)
|
||||||
}
|
})
|
||||||
})()
|
.catch(() => {}),
|
||||||
return () => {
|
)
|
||||||
cancelled = true
|
|
||||||
}
|
|
||||||
}, [source.repo, plugin.manifest.id])
|
}, [source.repo, plugin.manifest.id])
|
||||||
|
|
||||||
if (!listing || Object.keys(listing.channels).length === 0) return null
|
if (Object.keys(channels).length === 0) return null
|
||||||
|
|
||||||
const handleChange = async (selected: string) => {
|
const handleChange = (value: string) => {
|
||||||
if (selected === source.channel) return
|
setSelected(value)
|
||||||
|
|
||||||
const targetVersion = listing.channels[selected]
|
|
||||||
if (!targetVersion) return
|
|
||||||
|
|
||||||
|
const targetVersion = channels[value]!
|
||||||
if (targetVersion === plugin.manifest.version) {
|
if (targetVersion === plugin.manifest.version) {
|
||||||
setResetKey(k => k + 1)
|
|
||||||
ToastActionCreators.open({
|
ToastActionCreators.open({
|
||||||
key: 'REVENGE_PLUGIN_CHANNEL_UP_TO_DATE',
|
key: 'REVENGE_PLUGIN_VERSION_ALREADY_INSTALLED',
|
||||||
content: 'This channel is already installed',
|
content: 'This version is already installed',
|
||||||
IconComponent: () => <TableRowAssetIcon name="CircleCheckIcon" />,
|
IconComponent: () => <TableRowAssetIcon name="CircleCheckIcon" />,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const repos = await listRepos()
|
runInstallFlowWithInternalRepos(
|
||||||
const internalUrls = repos
|
|
||||||
.filter(r => r.internal)
|
|
||||||
.map(r => r.url)
|
|
||||||
|
|
||||||
ActionSheetActionCreators.hideActionSheet(sheetKey)
|
|
||||||
runInstallFlow(
|
|
||||||
plugin.manifest.id,
|
plugin.manifest.id,
|
||||||
undefined,
|
undefined,
|
||||||
selected,
|
value,
|
||||||
[...internalUrls, source.repo],
|
source.repo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRadioGroup
|
<TableRadioGroup
|
||||||
key={resetKey}
|
|
||||||
title="Channel"
|
title="Channel"
|
||||||
defaultValue={source.channel}
|
value={selected}
|
||||||
onChange={v => handleChange(v as string)}
|
onChange={v => handleChange(v as string)}
|
||||||
>
|
>
|
||||||
{Object.keys(listing.channels).map(c => (
|
{Object.keys(channels).map(c => (
|
||||||
<TableRadioRow key={c} label={c} value={c} />
|
<TableRadioRow key={c} label={c} value={c} />
|
||||||
))}
|
))}
|
||||||
</TableRadioGroup>
|
</TableRadioGroup>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function AdvancedSection({
|
function AdvancedSection({ plugin }: { plugin: AnyPlugin }) {
|
||||||
plugin,
|
|
||||||
sheetKey,
|
|
||||||
}: {
|
|
||||||
plugin: AnyPlugin
|
|
||||||
sheetKey: string
|
|
||||||
}) {
|
|
||||||
const meta = getInternalPluginMeta(plugin)
|
const meta = getInternalPluginMeta(plugin)
|
||||||
const dependents = getPluginDependents(plugin, true)
|
const dependents = getPluginDependents(plugin, true)
|
||||||
const dependencies = getPluginDependencies(plugin, false)
|
const dependencies = getPluginDependencies(plugin, false)
|
||||||
|
|
@ -266,73 +249,70 @@ function AdvancedSection({
|
||||||
const { id, name } = plugin.manifest
|
const { id, name } = plugin.manifest
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<TableRowGroup title="Advanced">
|
||||||
<ChannelSection plugin={plugin} sheetKey={sheetKey} />
|
<IdRow id={id} />
|
||||||
<TableRowGroup title="Advanced">
|
<RepositoryRow
|
||||||
<IdRow id={id} />
|
text={repositoryText}
|
||||||
<RepositoryRow
|
copyable={!!meta.source?.repo}
|
||||||
text={repositoryText}
|
/>
|
||||||
copyable={!!meta.source?.repo}
|
<TableRow
|
||||||
/>
|
icon={<TableRowAssetIcon name="FlagIcon" />}
|
||||||
|
label="Flags"
|
||||||
|
subLabel={bitFieldToString(PluginFlags, meta.flags)}
|
||||||
|
/>
|
||||||
|
{meta.iflags > 0 && (
|
||||||
<TableRow
|
<TableRow
|
||||||
icon={<TableRowAssetIcon name="FlagIcon" />}
|
icon={<TableRowAssetIcon name="FlagIcon" />}
|
||||||
label="Flags"
|
label="Internal Flags"
|
||||||
subLabel={bitFieldToString(PluginFlags, meta.flags)}
|
subLabel={bitFieldToString(
|
||||||
|
InternalPluginFlags,
|
||||||
|
meta.iflags,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
{meta.iflags > 0 && (
|
)}
|
||||||
<TableRow
|
{dependencies.length > 0 && (
|
||||||
icon={<TableRowAssetIcon name="FlagIcon" />}
|
<TableRow
|
||||||
label="Internal Flags"
|
icon={<TableRowAssetIcon name="ListBulletsIcon" />}
|
||||||
subLabel={bitFieldToString(
|
label="Dependencies"
|
||||||
InternalPluginFlags,
|
subLabel={`${name} depends on ${dependencies.length} other plugins`}
|
||||||
meta.iflags,
|
onPress={() => {
|
||||||
)}
|
ActionSheetActionCreators.openLazy(
|
||||||
/>
|
import('./PluginRelationsListActionSheet'),
|
||||||
)}
|
`plugin-deps-${id}`,
|
||||||
{dependencies.length > 0 && (
|
{
|
||||||
<TableRow
|
title: `Dependencies of ${name}`,
|
||||||
icon={<TableRowAssetIcon name="ListBulletsIcon" />}
|
unsatisfiedTitle: `Unsatisfied dependencies of ${name}`,
|
||||||
label="Dependencies"
|
unsatisfiedPlugins:
|
||||||
subLabel={`${name} depends on ${dependencies.length} other plugins`}
|
meta.unsatisfiedOptionalDependencies.map(
|
||||||
onPress={() => {
|
id => pList.get(id) ?? id,
|
||||||
ActionSheetActionCreators.openLazy(
|
),
|
||||||
import('./PluginRelationsListActionSheet'),
|
plugins: dependencies,
|
||||||
`plugin-deps-${id}`,
|
dependencyMap: plugin.manifest.dependencies!,
|
||||||
{
|
},
|
||||||
title: `Dependencies of ${name}`,
|
'stack',
|
||||||
unsatisfiedTitle: `Unsatisfied dependencies of ${name}`,
|
)
|
||||||
unsatisfiedPlugins:
|
}}
|
||||||
meta.unsatisfiedOptionalDependencies.map(
|
/>
|
||||||
id => pList.get(id) ?? id,
|
)}
|
||||||
),
|
{dependents.length > 0 && (
|
||||||
plugins: dependencies,
|
<TableRow
|
||||||
dependencyMap: plugin.manifest.dependencies!,
|
icon={<TableRowAssetIcon name="ListBulletsIcon" />}
|
||||||
},
|
label="Dependents"
|
||||||
'stack',
|
subLabel={`${dependents.length} other plugins depend on ${name}`}
|
||||||
)
|
onPress={() => {
|
||||||
}}
|
ActionSheetActionCreators.openLazy(
|
||||||
/>
|
import('./PluginRelationsListActionSheet'),
|
||||||
)}
|
`plugin-dependents-${id}`,
|
||||||
{dependents.length > 0 && (
|
{
|
||||||
<TableRow
|
title: `Dependents of ${name}`,
|
||||||
icon={<TableRowAssetIcon name="ListBulletsIcon" />}
|
plugins: dependents,
|
||||||
label="Dependents"
|
},
|
||||||
subLabel={`${dependents.length} other plugins depend on ${name}`}
|
'stack',
|
||||||
onPress={() => {
|
)
|
||||||
ActionSheetActionCreators.openLazy(
|
}}
|
||||||
import('./PluginRelationsListActionSheet'),
|
/>
|
||||||
`plugin-dependents-${id}`,
|
)}
|
||||||
{
|
</TableRowGroup>
|
||||||
title: `Dependents of ${name}`,
|
|
||||||
plugins: dependents,
|
|
||||||
},
|
|
||||||
'stack',
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableRowGroup>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,3 +170,21 @@ export async function runInstallFlow(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link runInstallFlow}, but automatically includes every internal repository plus
|
||||||
|
* the target repository in `filteredRepos`, so repo-installed plugins can be updated in place.
|
||||||
|
*/
|
||||||
|
export async function runInstallFlowWithInternalRepos(
|
||||||
|
id: string,
|
||||||
|
version?: string,
|
||||||
|
channel?: string,
|
||||||
|
repo?: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const repos = await listRepos()
|
||||||
|
const filteredRepos = repos
|
||||||
|
.filter(r => r.internal)
|
||||||
|
.map(r => r.url)
|
||||||
|
if (repo) filteredRepos.push(repo)
|
||||||
|
return runInstallFlow(id, version, channel, filteredRepos)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue