mirror of
https://github.com/modrinth/code.git
synced 2026-08-31 12:05:53 +00:00
feat: migrate all headers to use PageHeader shared component.
This commit is contained in:
@@ -194,6 +194,15 @@
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "No available versions match {compatibilityLabel}. Select a version to install anyway. Dependencies will not be installed automatically."
|
||||
},
|
||||
"app.browse.server.world-fallback-name": {
|
||||
"message": "Instance"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.title": {
|
||||
"message": "Installing modpack..."
|
||||
},
|
||||
"app.export-modal.description-placeholder": {
|
||||
"message": "Enter modpack description..."
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"
|
||||
>
|
||||
<template #default="{ onReinstall, onReinstallFailed }">
|
||||
<RouterView v-slot="{ Component }">
|
||||
<RouterView v-slot="{ Component }" :route="managedRoute">
|
||||
<template v-if="Component">
|
||||
<Suspense>
|
||||
<component
|
||||
@@ -46,7 +46,7 @@ import type { Archon, Labrinth } from '@modrinth/api-client'
|
||||
import { injectAuth, injectModrinthClient, ServersManageRootLayout } from '@modrinth/ui'
|
||||
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { computed, watch } from 'vue'
|
||||
import { computed, ref, shallowRef, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import { get_user } from '@/helpers/cache'
|
||||
@@ -60,10 +60,23 @@ const client = injectModrinthClient()
|
||||
const queryClient = useQueryClient()
|
||||
const breadcrumbs = useBreadcrumbs()
|
||||
|
||||
const serverId = computed(() => {
|
||||
const rawId = route.params.id
|
||||
return Array.isArray(rawId) ? rawId[0] : (rawId ?? '')
|
||||
})
|
||||
const managedRoute = shallowRef(router.currentRoute.value)
|
||||
const serverId = ref(getRouteParam(managedRoute.value.params.id) ?? '')
|
||||
|
||||
watch(
|
||||
router.currentRoute,
|
||||
(nextRoute) => {
|
||||
if (!nextRoute.path.startsWith('/hosting/manage/')) return
|
||||
managedRoute.value = nextRoute
|
||||
serverId.value = getRouteParam(nextRoute.params.id) ?? ''
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
function getRouteParam(param: string | string[] | undefined): string | null {
|
||||
if (Array.isArray(param)) return param[0] ?? null
|
||||
return param ?? null
|
||||
}
|
||||
|
||||
if (serverId.value) {
|
||||
try {
|
||||
|
||||
@@ -13,220 +13,57 @@
|
||||
@unlinked="fetchInstance"
|
||||
/>
|
||||
<UpdateToPlayModal ref="updateToPlayModal" :instance="instance" />
|
||||
<ContentPageHeader>
|
||||
<template #icon>
|
||||
<Avatar
|
||||
:src="icon ? icon : undefined"
|
||||
:alt="instance.name"
|
||||
size="64px"
|
||||
:tint-by="instance.id"
|
||||
/>
|
||||
</template>
|
||||
<template #title>
|
||||
{{ instance.name }}
|
||||
</template>
|
||||
<template #stats>
|
||||
<PageHeader
|
||||
:header="instance.name"
|
||||
:leading="instanceHeaderLeading"
|
||||
:metadata="instanceHeaderMetadata"
|
||||
:actions="instanceHeaderActions"
|
||||
>
|
||||
<template #metadata-server-details>
|
||||
<div class="flex items-center flex-wrap gap-2">
|
||||
<template v-if="!isServerInstance">
|
||||
<div class="flex min-w-0 items-center gap-2 font-medium text-secondary text-nowrap">
|
||||
<Gamepad2Icon class="flex size-5 shrink-0" aria-hidden="true" />
|
||||
<span class="truncate">{{ instance.game_version }}</span>
|
||||
</div>
|
||||
|
||||
<BulletDivider />
|
||||
|
||||
<div class="flex min-w-0 items-center gap-2 font-medium text-secondary text-nowrap">
|
||||
<ServerLoaderIcon
|
||||
v-if="loaderDisplayName"
|
||||
:loader="loaderDisplayName"
|
||||
class="flex size-5 shrink-0"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span class="truncate">{{ loaderLabel }}</span>
|
||||
</div>
|
||||
|
||||
<template v-if="showInstancePlayTime">
|
||||
<BulletDivider />
|
||||
|
||||
<div class="flex min-w-0 items-center gap-2 font-medium text-secondary text-nowrap">
|
||||
<TimerIcon class="flex size-5 shrink-0" aria-hidden="true" />
|
||||
<span class="truncate">
|
||||
{{ playtimeLabel }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<template v-if="loadingServerPing">
|
||||
<ServerOnlinePlayers
|
||||
v-if="playersOnline !== undefined"
|
||||
:online="playersOnline"
|
||||
:status-online="statusOnline"
|
||||
hide-label
|
||||
/>
|
||||
<ServerRecentPlays :recent-plays="recentPlays ?? 0" hide-label />
|
||||
<div
|
||||
v-if="
|
||||
(playersOnline !== undefined || recentPlays !== undefined) &&
|
||||
(minecraftServer?.region || ping)
|
||||
"
|
||||
class="w-1.5 h-1.5 rounded-full bg-surface-5"
|
||||
></div>
|
||||
<ServerPing v-if="ping" :ping="ping" />
|
||||
</template>
|
||||
|
||||
<ServerRegion v-if="minecraftServer?.region" :region="minecraftServer?.region" />
|
||||
|
||||
<template v-if="loadingServerPing">
|
||||
<ServerOnlinePlayers
|
||||
v-if="playersOnline !== undefined"
|
||||
:online="playersOnline"
|
||||
:status-online="statusOnline"
|
||||
hide-label
|
||||
/>
|
||||
<ServerRecentPlays :recent-plays="recentPlays ?? 0" hide-label />
|
||||
<div
|
||||
v-if="minecraftServer?.region || ping"
|
||||
v-if="
|
||||
(playersOnline !== undefined || recentPlays !== undefined) &&
|
||||
(minecraftServer?.region || ping)
|
||||
"
|
||||
class="w-1.5 h-1.5 rounded-full bg-surface-5"
|
||||
></div>
|
||||
|
||||
<div
|
||||
v-if="linkedProjectV3"
|
||||
class="flex gap-1.5 items-center font-medium text-primary"
|
||||
>
|
||||
Linked to
|
||||
<Avatar
|
||||
:src="linkedProjectV3.icon_url"
|
||||
:alt="linkedProjectV3.name"
|
||||
:tint-by="instance.id"
|
||||
size="24px"
|
||||
/>
|
||||
<router-link
|
||||
:to="`/project/${linkedProjectV3.slug ?? linkedProjectV3.id}`"
|
||||
class="hover:underline text-primary truncate"
|
||||
>
|
||||
{{ linkedProjectV3.name }}
|
||||
</router-link>
|
||||
</div>
|
||||
<ServerPing v-if="ping" :ping="ping" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions>
|
||||
<div class="flex gap-2">
|
||||
<ButtonStyled
|
||||
v-if="
|
||||
[
|
||||
'installing',
|
||||
'pack_installing',
|
||||
'pack_installed',
|
||||
'not_installed',
|
||||
'minecraft_installing',
|
||||
].includes(instance.install_stage)
|
||||
"
|
||||
color="brand"
|
||||
size="large"
|
||||
>
|
||||
<button disabled>Installing...</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled
|
||||
v-else-if="instance.install_stage !== 'installed'"
|
||||
color="brand"
|
||||
size="large"
|
||||
>
|
||||
<button @click="repairInstance()">
|
||||
<DownloadIcon />
|
||||
Repair
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-else-if="playing === true" color="red" size="large">
|
||||
<button :disabled="stopping" @click="stopInstance('InstancePage')">
|
||||
<StopCircleIcon />
|
||||
{{ stopping ? 'Stopping...' : 'Stop' }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled
|
||||
v-else-if="playing === false && loading === false && !isServerInstance"
|
||||
color="brand"
|
||||
size="large"
|
||||
>
|
||||
<button @click="startInstance('InstancePage')">
|
||||
<PlayIcon />
|
||||
Play
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<div
|
||||
v-else-if="playing === false && loading === false && isServerInstance"
|
||||
class="joined-buttons"
|
||||
>
|
||||
<ButtonStyled color="brand" size="large">
|
||||
<button @click="handlePlayServer()">
|
||||
<PlayIcon />
|
||||
Play
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="brand" size="large">
|
||||
<OverflowMenu
|
||||
:options="[
|
||||
{
|
||||
id: 'join_server',
|
||||
action: () => handlePlayServer(),
|
||||
},
|
||||
{
|
||||
id: 'launch_instance',
|
||||
action: () => startInstance('InstancePage'),
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div class="w-0 text-xl relative top-0.5 right-2.5">
|
||||
<DropdownIcon />
|
||||
</div>
|
||||
|
||||
<template #join_server>
|
||||
<PlayIcon />
|
||||
Join server
|
||||
</template>
|
||||
<template #launch_instance>
|
||||
<PlayIcon />
|
||||
Launch instance
|
||||
</template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
<ButtonStyled
|
||||
v-else-if="loading === true && playing === false"
|
||||
color="brand"
|
||||
size="large"
|
||||
>
|
||||
<button disabled>Starting...</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled circular size="large">
|
||||
<button v-tooltip="'Instance settings'" @click="settingsModal?.show()">
|
||||
<SettingsIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled type="transparent" circular size="large">
|
||||
<OverflowMenu
|
||||
:options="[
|
||||
{
|
||||
id: 'open-folder',
|
||||
action: () => {
|
||||
if (instance) showInstanceInFolder(instance.id)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'export-mrpack',
|
||||
action: () => exportModal?.show(),
|
||||
},
|
||||
{
|
||||
id: 'create-shortcut',
|
||||
action: () => createShortcut(),
|
||||
},
|
||||
]"
|
||||
<ServerRegion v-if="minecraftServer?.region" :region="minecraftServer?.region" />
|
||||
|
||||
<div
|
||||
v-if="minecraftServer?.region || ping"
|
||||
class="w-1.5 h-1.5 rounded-full bg-surface-5"
|
||||
></div>
|
||||
|
||||
<div v-if="linkedProjectV3" class="flex gap-1.5 items-center font-medium text-primary">
|
||||
Linked to
|
||||
<Avatar
|
||||
:src="linkedProjectV3.icon_url"
|
||||
:alt="linkedProjectV3.name"
|
||||
:tint-by="instance.id"
|
||||
size="24px"
|
||||
/>
|
||||
<router-link
|
||||
:to="`/project/${linkedProjectV3.slug ?? linkedProjectV3.id}`"
|
||||
class="hover:underline text-primary truncate"
|
||||
>
|
||||
<MoreVerticalIcon />
|
||||
<template #share-instance> <UserPlusIcon /> Share instance </template>
|
||||
<template #host-a-server> <ServerIcon /> Create a server </template>
|
||||
<template #open-folder> <FolderOpenIcon /> Open folder </template>
|
||||
<template #export-mrpack> <PackageIcon /> Export modpack </template>
|
||||
<template #create-shortcut> <ExternalIcon /> Create shortcut </template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
{{ linkedProjectV3.name }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ContentPageHeader>
|
||||
</PageHeader>
|
||||
</div>
|
||||
<div :class="['px-6', { 'shrink-0': isFixedRender }]">
|
||||
<NavTabs :links="tabs" />
|
||||
@@ -286,7 +123,6 @@ import {
|
||||
CheckCircleIcon,
|
||||
ClipboardCopyIcon,
|
||||
DownloadIcon,
|
||||
DropdownIcon,
|
||||
EditIcon,
|
||||
ExternalIcon,
|
||||
EyeIcon,
|
||||
@@ -297,26 +133,21 @@ import {
|
||||
PackageIcon,
|
||||
PlayIcon,
|
||||
PlusIcon,
|
||||
ServerIcon,
|
||||
SettingsIcon,
|
||||
StopCircleIcon,
|
||||
TagCategoryGamepad2Icon as Gamepad2Icon,
|
||||
TerminalSquareIcon,
|
||||
TimerIcon,
|
||||
UpdatedIcon,
|
||||
UserPlusIcon,
|
||||
XIcon,
|
||||
} from '@modrinth/assets'
|
||||
import {
|
||||
Avatar,
|
||||
BulletDivider,
|
||||
ButtonStyled,
|
||||
ContentPageHeader,
|
||||
formatLoaderLabel,
|
||||
injectNotificationManager,
|
||||
LoaderIcon as ServerLoaderIcon,
|
||||
NavTabs,
|
||||
OverflowMenu,
|
||||
PageHeader,
|
||||
ServerOnlinePlayers,
|
||||
ServerPing,
|
||||
ServerRecentPlays,
|
||||
@@ -774,6 +605,191 @@ const playtimeLabel = computed(() =>
|
||||
timePlayed.value > 0 ? timePlayedHumanized.value : 'Never played',
|
||||
)
|
||||
|
||||
const instanceHeaderLeading = computed(() => ({
|
||||
type: 'avatar' as const,
|
||||
src: icon.value ? icon.value : undefined,
|
||||
alt: instance.value?.name,
|
||||
avatarSize: '64px',
|
||||
tintBy: instance.value?.id,
|
||||
}))
|
||||
|
||||
const instanceHeaderMetadata = computed(() => {
|
||||
if (!instance.value) return []
|
||||
if (isServerInstance.value) {
|
||||
return [
|
||||
{
|
||||
id: 'server-details',
|
||||
type: 'custom' as const,
|
||||
class: 'contents',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'game-version',
|
||||
label: instance.value.game_version,
|
||||
icon: Gamepad2Icon,
|
||||
},
|
||||
{
|
||||
id: 'loader',
|
||||
label: loaderLabel.value,
|
||||
icon: ServerLoaderIcon,
|
||||
iconProps: {
|
||||
loader: loaderDisplayName.value,
|
||||
},
|
||||
},
|
||||
...(showInstancePlayTime.value
|
||||
? [
|
||||
{
|
||||
id: 'playtime',
|
||||
label: playtimeLabel.value,
|
||||
icon: TimerIcon,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]
|
||||
})
|
||||
|
||||
const installingStages = [
|
||||
'installing',
|
||||
'pack_installing',
|
||||
'pack_installed',
|
||||
'not_installed',
|
||||
'minecraft_installing',
|
||||
]
|
||||
|
||||
const primaryInstanceAction = computed(() => {
|
||||
if (!instance.value) return null
|
||||
|
||||
if (installingStages.includes(instance.value.install_stage)) {
|
||||
return {
|
||||
id: 'installing',
|
||||
label: 'Installing...',
|
||||
color: 'brand' as const,
|
||||
disabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
if (instance.value.install_stage !== 'installed') {
|
||||
return {
|
||||
id: 'repair',
|
||||
label: 'Repair',
|
||||
icon: DownloadIcon,
|
||||
color: 'brand' as const,
|
||||
onClick: () => {
|
||||
void repairInstance()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (playing.value === true) {
|
||||
return {
|
||||
id: 'stop',
|
||||
label: stopping.value ? 'Stopping...' : 'Stop',
|
||||
icon: StopCircleIcon,
|
||||
color: 'red' as const,
|
||||
disabled: stopping.value,
|
||||
onClick: () => {
|
||||
void stopInstance('InstancePage')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (playing.value === false && loading.value === false && !isServerInstance.value) {
|
||||
return {
|
||||
id: 'play',
|
||||
label: 'Play',
|
||||
icon: PlayIcon,
|
||||
color: 'brand' as const,
|
||||
onClick: () => {
|
||||
void startInstance('InstancePage')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (playing.value === false && loading.value === false && isServerInstance.value) {
|
||||
return {
|
||||
id: 'play',
|
||||
label: 'Play',
|
||||
color: 'brand' as const,
|
||||
joinedActions: [
|
||||
{
|
||||
id: 'join_server',
|
||||
label: 'Play',
|
||||
icon: PlayIcon,
|
||||
action: () => {
|
||||
void handlePlayServer()
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'launch_instance',
|
||||
label: 'Launch instance',
|
||||
icon: PlayIcon,
|
||||
action: () => {
|
||||
void startInstance('InstancePage')
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
if (loading.value === true && playing.value === false) {
|
||||
return {
|
||||
id: 'starting',
|
||||
label: 'Starting...',
|
||||
color: 'brand' as const,
|
||||
disabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
const instanceHeaderActions = computed(() => [
|
||||
...(primaryInstanceAction.value ? [primaryInstanceAction.value] : []),
|
||||
{
|
||||
id: 'settings',
|
||||
label: 'Instance settings',
|
||||
icon: SettingsIcon,
|
||||
labelHidden: true,
|
||||
tooltip: 'Instance settings',
|
||||
onClick: () => settingsModal.value?.show(),
|
||||
},
|
||||
{
|
||||
id: 'more',
|
||||
label: 'More actions',
|
||||
icon: MoreVerticalIcon,
|
||||
labelHidden: true,
|
||||
type: 'transparent' as const,
|
||||
tooltip: 'More actions',
|
||||
menuActions: [
|
||||
{
|
||||
id: 'open-folder',
|
||||
label: 'Open folder',
|
||||
icon: FolderOpenIcon,
|
||||
action: () => {
|
||||
if (instance.value) void showInstanceInFolder(instance.value.id)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'export-mrpack',
|
||||
label: 'Export modpack',
|
||||
icon: PackageIcon,
|
||||
action: () => exportModal.value?.show(),
|
||||
},
|
||||
{
|
||||
id: 'create-shortcut',
|
||||
label: 'Create shortcut',
|
||||
icon: ExternalIcon,
|
||||
action: () => {
|
||||
void createShortcut()
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
onUnmounted(() => {
|
||||
unlistenProcesses()
|
||||
unlistenInstances()
|
||||
|
||||
@@ -64,121 +64,9 @@
|
||||
:project="data"
|
||||
:project-v3="projectV3"
|
||||
:ping="serverPing"
|
||||
:actions="projectHeaderActions"
|
||||
@contextmenu.prevent.stop="handleRightClick"
|
||||
>
|
||||
<template v-if="isServerProject" #actions>
|
||||
<ButtonStyled v-if="serverPlaying" size="large" color="red">
|
||||
<button @click="handleStopServer">
|
||||
<StopCircleIcon />
|
||||
{{ formatMessage(commonMessages.stopButton) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-else size="large" color="brand">
|
||||
<button
|
||||
:disabled="data && installingServerProjects.includes(data.id)"
|
||||
@click="handleClickPlay"
|
||||
>
|
||||
<PlayIcon />
|
||||
{{
|
||||
data && installingServerProjects.includes(data.id)
|
||||
? formatMessage(commonMessages.installingLabel)
|
||||
: formatMessage(commonMessages.playButton)
|
||||
}}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled size="large" circular>
|
||||
<button
|
||||
v-tooltip="formatMessage(commonMessages.addServerToInstanceButton)"
|
||||
@click="handleAddServerToInstance"
|
||||
>
|
||||
<PlusIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled size="large" circular type="transparent">
|
||||
<OverflowMenu
|
||||
:tooltip="`More options`"
|
||||
:options="[
|
||||
{
|
||||
id: 'open-in-browser',
|
||||
link: `https://modrinth.com/project/${data.slug}`,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
id: 'report',
|
||||
color: 'red',
|
||||
hoverFilled: true,
|
||||
link: `https://modrinth.com/report?item=project&itemID=${data.id}`,
|
||||
},
|
||||
]"
|
||||
aria-label="More options"
|
||||
>
|
||||
<MoreVerticalIcon aria-hidden="true" />
|
||||
<template #open-in-browser> <ExternalIcon /> Open in browser </template>
|
||||
<template #report> <ReportIcon /> Report </template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
<template v-else #actions>
|
||||
<ButtonStyled size="large" color="brand">
|
||||
<button
|
||||
v-tooltip="installButtonTooltip"
|
||||
:disabled="installButtonDisabled"
|
||||
@click="install(null)"
|
||||
>
|
||||
<SpinnerIcon
|
||||
v-if="installButtonLoading && !installButtonInstalled"
|
||||
class="animate-spin"
|
||||
/>
|
||||
<DownloadIcon v-else-if="!installButtonInstalled && !serverProjectSelected" />
|
||||
<CheckIcon v-else />
|
||||
{{ installButtonLabel }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled size="large" circular type="transparent">
|
||||
<OverflowMenu
|
||||
:tooltip="`More options`"
|
||||
:options="[
|
||||
{
|
||||
id: 'follow',
|
||||
disabled: true,
|
||||
tooltip: 'Coming soon',
|
||||
action: () => {},
|
||||
},
|
||||
{
|
||||
id: 'save',
|
||||
disabled: true,
|
||||
tooltip: 'Coming soon',
|
||||
action: () => {},
|
||||
},
|
||||
{
|
||||
id: 'open-in-browser',
|
||||
link: `https://modrinth.com/${data.project_type}/${data.slug}`,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
id: 'report',
|
||||
color: 'red',
|
||||
hoverFilled: true,
|
||||
link: `https://modrinth.com/report?item=project&itemID=${data.id}`,
|
||||
},
|
||||
]"
|
||||
aria-label="More options"
|
||||
>
|
||||
<MoreVerticalIcon aria-hidden="true" />
|
||||
<template #open-in-browser> <ExternalIcon /> Open in browser </template>
|
||||
<template #follow> <HeartIcon /> Follow </template>
|
||||
<template #save> <BookmarkIcon /> Save </template>
|
||||
<template #report> <ReportIcon /> Report </template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
</ProjectHeader>
|
||||
/>
|
||||
<NavTabs
|
||||
:links="[
|
||||
{
|
||||
@@ -266,14 +154,12 @@ import {
|
||||
} from '@modrinth/assets'
|
||||
import {
|
||||
BrowseInstallHeader,
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
CreationFlowModal,
|
||||
defineMessages,
|
||||
getTargetInstallPreferences,
|
||||
injectNotificationManager,
|
||||
NavTabs,
|
||||
OverflowMenu,
|
||||
ProjectBackgroundGradient,
|
||||
ProjectHeader,
|
||||
ProjectSidebarCompatibility,
|
||||
@@ -514,6 +400,131 @@ const installButtonTooltip = computed(() => {
|
||||
return null
|
||||
})
|
||||
|
||||
const projectHeaderActions = computed(() => {
|
||||
if (!data.value) return []
|
||||
|
||||
if (isServerProject.value) {
|
||||
return [
|
||||
serverPlaying.value
|
||||
? {
|
||||
id: 'stop',
|
||||
label: formatMessage(commonMessages.stopButton),
|
||||
icon: StopCircleIcon,
|
||||
color: 'red',
|
||||
onClick: handleStopServer,
|
||||
}
|
||||
: {
|
||||
id: 'play',
|
||||
label:
|
||||
data.value && installingServerProjects.value.includes(data.value.id)
|
||||
? formatMessage(commonMessages.installingLabel)
|
||||
: formatMessage(commonMessages.playButton),
|
||||
icon: PlayIcon,
|
||||
color: 'brand',
|
||||
disabled: data.value && installingServerProjects.value.includes(data.value.id),
|
||||
onClick: handleClickPlay,
|
||||
},
|
||||
{
|
||||
id: 'add-server-to-instance',
|
||||
label: formatMessage(commonMessages.addServerToInstanceButton),
|
||||
icon: PlusIcon,
|
||||
labelHidden: true,
|
||||
tooltip: formatMessage(commonMessages.addServerToInstanceButton),
|
||||
onClick: handleAddServerToInstance,
|
||||
},
|
||||
{
|
||||
id: 'more',
|
||||
label: 'More options',
|
||||
icon: MoreVerticalIcon,
|
||||
labelHidden: true,
|
||||
type: 'transparent',
|
||||
tooltip: 'More options',
|
||||
menuActions: [
|
||||
{
|
||||
id: 'open-in-browser',
|
||||
label: 'Open in browser',
|
||||
icon: ExternalIcon,
|
||||
action: () => openUrl(`https://modrinth.com/project/${data.value.slug}`),
|
||||
},
|
||||
{
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
id: 'report',
|
||||
label: 'Report',
|
||||
icon: ReportIcon,
|
||||
color: 'red',
|
||||
action: () =>
|
||||
openUrl(`https://modrinth.com/report?item=project&itemID=${data.value.id}`),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'install',
|
||||
label: installButtonLabel.value,
|
||||
icon:
|
||||
installButtonLoading.value && !installButtonInstalled.value
|
||||
? SpinnerIcon
|
||||
: !installButtonInstalled.value && !serverProjectSelected.value
|
||||
? DownloadIcon
|
||||
: CheckIcon,
|
||||
iconClass:
|
||||
installButtonLoading.value && !installButtonInstalled.value ? 'animate-spin' : undefined,
|
||||
color: 'brand',
|
||||
tooltip: installButtonTooltip.value,
|
||||
disabled: installButtonDisabled.value,
|
||||
onClick: () => install(null),
|
||||
},
|
||||
{
|
||||
id: 'more',
|
||||
label: 'More options',
|
||||
icon: MoreVerticalIcon,
|
||||
labelHidden: true,
|
||||
type: 'transparent',
|
||||
tooltip: 'More options',
|
||||
menuActions: [
|
||||
{
|
||||
id: 'follow',
|
||||
label: 'Follow',
|
||||
icon: HeartIcon,
|
||||
disabled: true,
|
||||
tooltip: 'Coming soon',
|
||||
action: () => {},
|
||||
},
|
||||
{
|
||||
id: 'save',
|
||||
label: 'Save',
|
||||
icon: BookmarkIcon,
|
||||
disabled: true,
|
||||
tooltip: 'Coming soon',
|
||||
action: () => {},
|
||||
},
|
||||
{
|
||||
id: 'open-in-browser',
|
||||
label: 'Open in browser',
|
||||
icon: ExternalIcon,
|
||||
action: () =>
|
||||
openUrl(`https://modrinth.com/${data.value.project_type}/${data.value.slug}`),
|
||||
},
|
||||
{
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
id: 'report',
|
||||
label: 'Report',
|
||||
icon: ReportIcon,
|
||||
color: 'red',
|
||||
action: () => openUrl(`https://modrinth.com/report?item=project&itemID=${data.value.id}`),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const [allLoaders, allGameVersions] = await Promise.all([
|
||||
get_loaders().catch(handleError).then(ref),
|
||||
get_game_versions().catch(handleError).then(ref),
|
||||
|
||||
Reference in New Issue
Block a user