feat: depends on search filter (#6713)

* feat: add norisk client source support (#6707)

Signed-off-by: Robin <me@orb1n.dev>

* changelog

* feat: implement depends on search filter

* feat: add modpack "includes content" filter and update depends on

* feat: style pass

* feat: show included modpack projects filter tag better

* pnpm prepr

* feat: polish depends on filter

* fix: clear button, page scroll, and metadata loading state

* feat: hook up excludes modpack

* fix: combobox closing race

* Revert "fix: combobox closing race"

This reverts commit e51529ca65.

* fix scrolling after applying depends on

* feedback

* pnpm prepr

* slightly make buttons larger for touch devices

* feat: add view dependents/view modpacks in project overflow menu

* pnpm prepr

* fix: divider

* add icon

* fix: project search combobox background in app

---------

Signed-off-by: Robin <me@orb1n.dev>
Co-authored-by: Robin <robin.murer11@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
Truman Gao
2026-08-20 19:01:17 +00:00
committed by GitHub
co-authored by Robin Prospector
parent 5d54cfa0dc
commit 5181370293
17 changed files with 991 additions and 110 deletions
@@ -3494,6 +3494,15 @@
"project.actions.servers-promo.title": {
"message": "Create a server"
},
"project.actions.view-dependents": {
"message": "View dependents"
},
"project.actions.view-modpacks": {
"message": "View modpacks"
},
"project.actions.view-project-type-dependents": {
"message": "View {projectType} dependents"
},
"project.ai-image-warning-modal.body.1": {
"message": "Using AI-generated images to represent your project is not allowed. Attempting to work around detection may lead to your Modrinth account being suspended."
},
+78 -1
View File
@@ -564,10 +564,12 @@ import {
HeartIcon,
LeftArrowIcon,
MoreVerticalIcon,
PackageSearchIcon,
PlayIcon,
ReportIcon,
ScaleIcon,
ScanEyeIcon,
SearchIcon,
ServerPlusIcon,
SettingsIcon,
XIcon,
@@ -582,6 +584,8 @@ import {
ButtonLink,
commonMessages,
defineMessages,
formatDependencyProjectFilterOption,
formatProjectTypeSentence,
getActiveDisclosures,
IconButton,
injectModrinthClient,
@@ -846,6 +850,18 @@ const messages = defineMessages({
id: 'project.actions.review-project',
defaultMessage: 'Review project',
},
viewDependents: {
id: 'project.actions.view-dependents',
defaultMessage: 'View dependents',
},
viewProjectTypeDependents: {
id: 'project.actions.view-project-type-dependents',
defaultMessage: 'View {projectType} dependents',
},
viewModpacks: {
id: 'project.actions.view-modpacks',
defaultMessage: 'View modpacks',
},
rescanModpack: {
id: 'project.actions.rescan-modpack',
defaultMessage: 'Rescan modpack',
@@ -1904,6 +1920,30 @@ async function checkModpackArchives() {
const projectHeaderMoreActions = computed(() => {
const isStaff = !!(auth.value.user && tags.value.staffRoles.includes(auth.value.user.role))
const projectId = project.value?.id
const dependentSearchTypes = getDependentSearchTypes()
const dependentSearchActions = dependentSearchTypes
.filter((projectType) => projectType !== 'modpack')
.map((projectType) => ({
id: `view-${projectType}-dependents`,
label: formatMessage(
dependentSearchTypes.length === 1
? messages.viewDependents
: messages.viewProjectTypeDependents,
{
projectType: formatProjectTypeSentence(formatMessage, projectType),
},
),
icon: SearchIcon,
type: 'link',
to: {
path: `/discover/${projectType}s`,
query: {
dep: formatDependencyProjectFilterOption(projectId, ['required']),
},
},
}))
const isPluginOnly = dependentSearchTypes.length === 1 && dependentSearchTypes[0] === 'plugin'
return [
{
@@ -1914,7 +1954,21 @@ const projectHeaderMoreActions = computed(() => {
to: `${projectPath.value}/settings/analytics`,
shown: !!auth.value.user && !!currentMember.value,
},
{ type: 'divider', shown: !!auth.value.user && !!currentMember.value },
...dependentSearchActions,
{
id: 'view-modpacks',
label: formatMessage(messages.viewModpacks),
icon: PackageSearchIcon,
type: 'link',
to: {
path: '/discover/modpacks',
query: {
dep: formatDependencyProjectFilterOption(projectId, ['required']),
},
},
shown: !isPluginOnly && project.value?.actualProjectType !== 'modpack',
},
{ type: 'divider' },
{
id: 'moderation-checklist',
label: formatMessage(messages.reviewProject),
@@ -1977,6 +2031,29 @@ const projectHeaderMoreActions = computed(() => {
]
})
function getDependentSearchTypes() {
if (!project.value) return []
if (project.value.actualProjectType !== 'mod') {
return [isServerProject.value ? 'server' : project.value.actualProjectType]
}
const loaders = project.value.loaders ?? []
const projectTypes = []
if (loaders.some((loader) => tags.value.loaderData.modLoaders.includes(loader))) {
projectTypes.push('mod')
}
if (loaders.some((loader) => tags.value.loaderData.allPluginLoaders.includes(loader))) {
projectTypes.push('plugin')
}
if (loaders.some((loader) => tags.value.loaderData.dataPackLoaders.includes(loader))) {
projectTypes.push('datapack')
}
return projectTypes.length > 0 ? projectTypes : ['mod']
}
const createCanonicalUrl = () =>
project.value ? `https://modrinth.com/project/${project.value.id}` : undefined