Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/app-frontend/src/locales/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@
"app.browse.hide-added-servers": {
"message": "Hide servers already added"
},
"app.browse.hide-installed-modpacks": {
"message": "Hide already installed"
},
"app.browse.project-type.modpacks": {
"message": "Modpacks"
},
Expand Down
119 changes: 92 additions & 27 deletions apps/app-frontend/src/pages/Browse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { instance_listener } from '@/helpers/events.js'
import {
get as getInstance,
get_installed_project_ids as getInstalledProjectIds,
list as listInstances,
} from '@/helpers/instance'
import { get_loader_versions as getLoaderManifest } from '@/helpers/metadata'
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
Expand Down Expand Up @@ -171,7 +172,7 @@ const instance: Ref<Instance | null> = ref(
queryClient.getQueryData<Instance>(['instances', 'summary', initialInstanceId]) ?? null,
)
const installedProjectIds: Ref<string[] | null> = ref(null)
const instanceHideInstalled = ref(false)
const instanceHideInstalled = ref(route.query.ai === 'true')
const newlyInstalled = ref<string[]>([])
const hiddenInstanceProjectIds = ref<Set<string>>(new Set())
const hiddenInstanceProjectIdsInitialized = ref(false)
Expand Down Expand Up @@ -288,7 +289,17 @@ watchServerContextChanges()
await initInstanceContext()

async function refreshInstalledProjectIds() {
if (!route.query.i) return
if (!route.query.i) {
const instances = await listInstances().catch(handleError)
if (!instances) return

const ids = instances
.map((gameInstance) => gameInstance.link?.project_id)
.filter((id): id is string => !!id)
debugLog('installedInstanceProjectIds loaded', { count: ids.length })
installedProjectIds.value = ids
return
}

if (route.query.from === 'worlds') {
const worlds = await get_instance_worlds(route.query.i as string).catch(handleError)
Expand Down Expand Up @@ -318,6 +329,7 @@ async function initInstanceContext() {
queryFrom: route.query.from,
})
await initServerContext()
await refreshInstalledProjectIds()

if (route.query.i) {
instance.value = (await getInstance(route.query.i as string).catch(handleError)) ?? null
Expand All @@ -327,8 +339,6 @@ async function initInstanceContext() {
gameVersion: instance.value?.game_version,
})

await refreshInstalledProjectIds()

if (instance.value?.link?.project_id) {
debugLog('checking linked project for server status', instance.value.link.project_id)
const projectV3 = await get_project_v3(
Expand All @@ -341,13 +351,23 @@ async function initInstanceContext() {
}
}
}
}

if (route.query.ai && !(route.params.projectType === 'modpack')) {
debugLog('setting instanceHideInstalled from query', route.query.ai)
instanceHideInstalled.value = route.query.ai === 'true'
}
function setBrowseHideInstalledFlag(flag: 'hide_installed_modpacks', value: boolean) {
themeStore.featureFlags[flag] = value
getSettings()
.then((settings) => {
settings.feature_flags[flag] = value
return setSettings(settings)
})
.catch(handleError)
}

const hideInstalledModpacks = computed({
get: () => themeStore.getFeatureFlag('hide_installed_modpacks'),
set: (value: boolean) => setBrowseHideInstalledFlag('hide_installed_modpacks', value),
})

const instanceFilters = computed(() => {
const filters = []

Expand All @@ -367,11 +387,15 @@ const instanceFilters = computed(() => {
if (isServerInstance.value) {
filters.push({ type: 'environment', option: 'client' })
}
}

if (instanceHideInstalled.value && hiddenInstanceProjectIds.value.size > 0) {
for (const id of hiddenInstanceProjectIds.value) {
filters.push({ type: 'project_id', option: `project_id:${id}`, negative: true })
}
if (
(instance.value || projectType.value === 'modpack') &&
(projectType.value === 'modpack' ? hideInstalledModpacks.value : instanceHideInstalled.value) &&
hiddenInstanceProjectIds.value.size > 0
) {
for (const id of hiddenInstanceProjectIds.value) {
filters.push({ type: 'project_id', option: `project_id:${id}`, negative: true })
}
}

Expand Down Expand Up @@ -430,6 +454,12 @@ const serverContextFilters = computed(() => {
{ type: 'environment', option: 'client' },
{ type: 'environment', option: 'server' },
)

if (hideInstalledModpacks.value && hiddenInstanceProjectIds.value.size > 0) {
for (const id of hiddenInstanceProjectIds.value) {
filters.push({ type: 'project_id', option: `project_id:${id}`, negative: true })
}
}
}

if (serverHideInstalled.value && hiddenServerContentProjectIds.value.size > 0) {
Expand Down Expand Up @@ -500,6 +530,10 @@ const messages = defineMessages({
id: 'app.browse.hide-added-servers',
defaultMessage: 'Hide servers already added',
},
hideInstalledModpacks: {
id: 'app.browse.hide-installed-modpacks',
defaultMessage: 'Hide already installed',
},
installingToServer: {
id: 'app.browse.server.installing',
defaultMessage: 'Installing',
Expand Down Expand Up @@ -553,6 +587,7 @@ function resetInstanceContext() {
hiddenInstanceProjectIdsInitialized.value = false
isServerInstance.value = false
browseBreadcrumb.reset()
void refreshInstalledProjectIds()
}

watch(
Expand Down Expand Up @@ -781,6 +816,7 @@ function getCardActions(
serverContentProjectIds.value.has(projectResult.project_id || '') ||
serverContextServerData.value?.upstream?.project_id === projectResult.project_id
const isInstalling = installingProjectIds.value.has(projectResult.project_id)
const showAsInstalled = isInstalled && currentProjectType !== 'modpack'

if (
isServerContext.value &&
Expand All @@ -790,7 +826,7 @@ function getCardActions(
const isInstallingSelection = isInstallingQueuedServerInstalls.value
const validatingInstall =
isInstalling && currentProjectType !== 'modpack' && !isInstallingSelection
const installLabel = isInstalled
const installLabel = showAsInstalled
? commonMessages.installedLabel
: isQueued
? isInstalling || isInstallingSelection
Expand All @@ -810,11 +846,11 @@ function getCardActions(
icon:
isInstalling || isInstallingSelection
? SpinnerIcon
: isQueued || isInstalled
: isQueued || showAsInstalled
? CheckIcon
: PlusIcon,
iconClass: isInstalling || isInstallingSelection ? 'animate-spin' : undefined,
disabled: isInstalled || isInstalling || isInstallingSelection,
disabled: showAsInstalled || isInstalling || isInstallingSelection,
color: isQueued && !isInstalling && !isInstallingSelection ? 'green' : 'brand',
type: 'outlined',
onClick: async () => {
Expand Down Expand Up @@ -875,15 +911,15 @@ function getCardActions(
label: formatMessage(
isInstalling
? messages.installingToServer
: isInstalled
: showAsInstalled
? commonMessages.installedLabel
: shouldUseInstallIcon
? commonMessages.installButton
: messages.addToAnInstance,
),
icon: isInstalling ? SpinnerIcon : isInstalled ? CheckIcon : PlusIcon,
icon: isInstalling ? SpinnerIcon : showAsInstalled ? CheckIcon : PlusIcon,
iconClass: isInstalling ? 'animate-spin' : undefined,
disabled: isInstalled || isInstalling,
disabled: showAsInstalled || isInstalling,
color: 'brand',
type: 'outlined',
onClick: async () => {
Expand Down Expand Up @@ -994,10 +1030,11 @@ async function search(requestParams: string) {
...hit,
}

if (instance.value || isServerContext.value) {
const installedIds = instance.value
? new Set([...newlyInstalled.value, ...(installedProjectIds.value ?? [])])
: serverContentProjectIds.value
if (instance.value || isServerContext.value || projectType.value === 'modpack') {
const installedIds =
isServerContext.value && projectType.value !== 'modpack'
? serverContentProjectIds.value
: new Set([...newlyInstalled.value, ...(installedProjectIds.value ?? [])])
mapped.installed = installedIds.has(hit.project_id)
}

Expand Down Expand Up @@ -1057,9 +1094,9 @@ watch(
() => projectType.value,
],
() => {
if (isServerContext.value) {
if (isServerContext.value && projectType.value !== 'modpack') {
syncHiddenServerContentProjectIds()
} else if (instance.value) {
} else if (instance.value || projectType.value === 'modpack') {
syncHiddenInstanceProjectIds()
}
},
Expand Down Expand Up @@ -1091,6 +1128,18 @@ let unlistenInstances: UnlistenFn | null = null

onMounted(() => {
instance_listener(async (event: { event: string; instance_id: string }) => {
if (event.event === 'added' || event.event === 'created' || event.event === 'removed') {
if (!route.query.i) {
await refreshInstalledProjectIds()
if (projectType.value === 'modpack') {
if (event.event === 'removed') {
syncHiddenInstanceProjectIds()
}
await searchState.refreshSearch()
}
}
}

if (instance.value && event.instance_id === instance.value.id && event.event === 'synced') {
await refreshInstalledProjectIds()
await searchState.refreshSearch()
Expand Down Expand Up @@ -1156,8 +1205,17 @@ provideBrowseManager({
installContext,
providedFilters: combinedProvidedFilters,
hideInstalled: computed({
get: () => (isServerContext.value ? serverHideInstalled.value : instanceHideInstalled.value),
get: () => {
if (projectType.value === 'modpack') return hideInstalledModpacks.value
if (isServerContext.value) return serverHideInstalled.value
return instanceHideInstalled.value
},
set: (val: boolean) => {
if (projectType.value === 'modpack') {
hideInstalledModpacks.value = val
if (val) syncHiddenInstanceProjectIds()
return
}
if (isServerContext.value) {
serverHideInstalled.value = val
if (val) syncHiddenServerContentProjectIds()
Expand All @@ -1168,11 +1226,18 @@ provideBrowseManager({
},
}),
showHideInstalled: computed(
() => (isServerContext.value && projectType.value !== 'modpack') || !!instance.value,
() =>
projectType.value === 'modpack' ||
(isServerContext.value && projectType.value !== 'modpack') ||
!!instance.value,
),
hideInstalledLabel: computed(() =>
formatMessage(
isFromWorlds.value ? messages.hideAddedServers : commonMessages.hideInstalledContentLabel,
isFromWorlds.value
? messages.hideAddedServers
: projectType.value === 'modpack'
? messages.hideInstalledModpacks
: commonMessages.hideInstalledContentLabel,
),
),
hideSelected: hideSelectedServerInstalls,
Expand Down
1 change: 1 addition & 0 deletions apps/app-frontend/src/store/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const DEFAULT_FEATURE_FLAGS = {
show_instance_play_time: true,
advanced_filters_collapsed: true,
always_show_copy_details: false,
hide_installed_modpacks: false,
}

export const THEME_OPTIONS = ['dark', 'light', 'oled', 'retro', 'system'] as const
Expand Down
1 change: 1 addition & 0 deletions packages/app-lib/src/state/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub enum FeatureFlag {
SkipNonEssentialWarnings,
AdvancedFiltersCollapsed,
AlwaysShowCopyDetails,
HideInstalledModpacks,
}

impl Settings {
Expand Down
Loading