Skip to content
Draft
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
1 change: 1 addition & 0 deletions apps/app-frontend/src/pages/hosting/manage/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
:reload-page="() => router.go(0)"
:resolve-viewer="resolveViewer"
:show-copy-id-action="themeStore.devMode"
:show-play-tab="themeStore.getFeatureFlag('ServerPlayFrontend')"
:auth-user="authUser"
:navigate-to-billing="() => openUrl('https://modrinth.com/settings/billing')"
:navigate-to-servers="() => router.push('/hosting/manage')"
Expand Down
18 changes: 18 additions & 0 deletions apps/app-frontend/src/pages/hosting/manage/Play.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import { ServersManagePlayPage } from '@modrinth/ui'
import { useRoute, useRouter } from 'vue-router'

import { useTheming } from '@/store/theme'

const route = useRoute()
const router = useRouter()
const themeStore = useTheming()

if (!themeStore.getFeatureFlag('ServerPlayFrontend')) {
await router.replace(`/hosting/manage/${String(route.params.id)}`)
}
</script>

<template>
<ServersManagePlayPage />
</template>
3 changes: 2 additions & 1 deletion apps/app-frontend/src/pages/hosting/manage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import Content from './Content.vue'
import Files from './Files.vue'
import Index from './Index.vue'
import Overview from './Overview.vue'
import Play from './Play.vue'

export { Access, Backups, Content, Files, Index, Overview }
export { Access, Backups, Content, Files, Index, Overview, Play }
5 changes: 5 additions & 0 deletions apps/app-frontend/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export default new createRouter({
name: 'ServerManage',
component: Hosting.Index,
children: [
{
path: 'play',
name: 'ServerManagePlay',
component: Hosting.Play,
},
{
path: '',
name: 'ServerManageOverview',
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 @@ -18,6 +18,7 @@ export const DEFAULT_FEATURE_FLAGS = {
advanced_filters_collapsed: true,
always_show_copy_details: false,
hide_installed_modpacks: false,
ServerPlayFrontend: false,
}

export const THEME_OPTIONS = ['dark', 'light', 'oled', 'retro', 'system'] as const
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/src/composables/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({
versionDevInfoCollapsed: true,
alwaysShowVersionDevInfo: false,
advancedFiltersCollapsed: true,
ServerPlayFrontend: false,
} as const)

export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/src/pages/hosting/manage/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:resolve-viewer="resolveViewer"
:show-copy-id-action="flags.developerMode"
:show-advanced-debug-info="flags.advancedDebugInfo"
:show-play-tab="flags.ServerPlayFrontend"
:stripe-publishable-key="config.public.stripePublishableKey as string"
:site-url="config.public.siteUrl as string"
:products="products"
Expand Down
19 changes: 19 additions & 0 deletions apps/frontend/src/pages/hosting/manage/[id]/play.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup lang="ts">
import { injectModrinthServerContext, ServersManagePlayPage } from '@modrinth/ui'
const { server } = injectModrinthServerContext()
const flags = useFeatureFlags()
const route = useNativeRoute()
if (!flags.value.ServerPlayFrontend) {
await navigateTo(`/hosting/manage/${String(route.params.id)}`, { replace: true })
}
useHead({
title: computed(() => `Play - ${server.value?.name ?? 'Server'} - Modrinth`),
})
</script>

<template>
<ServersManagePlayPage />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<template>
<section
class="flex flex-col gap-4 rounded-[20px] border border-solid border-surface-4 bg-surface-3 p-5"
>
<div class="flex flex-col gap-8 md:flex-row md:items-center">
<div class="flex min-w-0 flex-1 flex-col gap-0.5">
<h2 class="m-0 text-xl font-semibold text-contrast">
{{ formatMessage(messages.playWithAppTitle) }}
</h2>
<p class="m-0 text-base leading-6 text-primary">
{{ formatMessage(messages.playWithAppDescription) }}
</p>
</div>
<div class="flex shrink-0 flex-col gap-2 md:w-[164px]">
<ButtonStyled color="brand">
<button class="!h-10 w-full" @click="emit('play')">
<PlayIcon aria-hidden="true" />
{{ formatMessage(messages.playServerButton) }}
</button>
</ButtonStyled>
<ButtonStyled>
<button class="!h-10 w-full" @click="emit('invite')">
<UserPlusIcon aria-hidden="true" />
{{ formatMessage(messages.invitePlayersButton) }}
</button>
</ButtonStyled>
</div>
</div>

<div class="flex flex-col gap-3">
<div class="h-px w-full bg-surface-4"></div>
<div class="flex flex-col gap-0.5">
<h2 class="m-0 text-xl font-semibold text-contrast">
{{ formatMessage(messages.differentLauncherTitle) }}
</h2>
<p class="m-0 text-base leading-6 text-primary">
{{ formatMessage(messages.differentLauncherDescription) }}
</p>
</div>
<div class="flex flex-col gap-2 sm:flex-row sm:items-center">
<div class="joined-buttons shrink-0">
<ButtonStyled>
<a
v-if="modpackDownloadUrl"
class="!h-10"
:href="modpackDownloadUrl"
:download="modpackFilename"
>
<DownloadIcon aria-hidden="true" />
{{ formatMessage(messages.downloadModpackButton) }}
</a>
<button v-else type="button" class="!h-10">
<DownloadIcon aria-hidden="true" />
{{ formatMessage(messages.downloadModpackButton) }}
</button>
</ButtonStyled>
<ButtonStyled>
<a
v-if="modpackDownloadUrl"
v-tooltip="formatMessage(messages.downloadModpackButton)"
class="!h-10 !w-10 !px-0"
:href="modpackDownloadUrl"
:download="modpackFilename"
:aria-label="formatMessage(messages.downloadModpackButton)"
>
<ChevronDownIcon aria-hidden="true" />
</a>
<button
v-else
v-tooltip="formatMessage(messages.downloadModpackButton)"
type="button"
class="!h-10 !w-10 !px-0"
:aria-label="formatMessage(messages.downloadModpackButton)"
>
<ChevronDownIcon aria-hidden="true" />
</button>
</ButtonStyled>
</div>
<div
class="flex h-10 min-w-0 items-center justify-between gap-3 rounded-xl bg-surface-2 px-4 sm:w-[313px]"
>
<span class="min-w-0 truncate font-semibold text-primary">{{ address }}</span>
<button
v-tooltip="formatMessage(copied ? messages.copiedAddress : messages.copyAddress)"
type="button"
class="flex shrink-0 cursor-pointer items-center border-0 bg-transparent p-0 text-primary"
:aria-label="formatMessage(copied ? messages.copiedAddress : messages.copyAddress)"
@click="copyAddress"
>
<CheckIcon v-if="copied" class="size-5 text-brand" aria-hidden="true" />
<CopyIcon v-else class="size-5" aria-hidden="true" />
</button>
</div>
</div>
</div>
</section>
</template>

<script setup lang="ts">
import {
CheckIcon,
ChevronDownIcon,
CopyIcon,
DownloadIcon,
PlayIcon,
UserPlusIcon,
} from '@modrinth/assets'
import { ref } from 'vue'

import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'

const props = defineProps<{
address: string
modpackDownloadUrl?: string
modpackFilename?: string
}>()

const emit = defineEmits<{
play: []
invite: []
}>()

const { formatMessage } = useVIntl()
const copied = ref(false)

const messages = defineMessages({
playWithAppTitle: {
id: 'servers.play.card.app.title',
defaultMessage: 'Play with Modrinth App',
},
playWithAppDescription: {
id: 'servers.play.card.app.description',
defaultMessage:
'The easiest way to play is with the Modrinth App, which automatically installs all the required content for you and the players on your server.',
},
playServerButton: {
id: 'servers.play.card.app.play-button',
defaultMessage: 'Play server',
},
invitePlayersButton: {
id: 'servers.play.card.app.invite-button',
defaultMessage: 'Invite players',
},
differentLauncherTitle: {
id: 'servers.play.card.launcher.title',
defaultMessage: 'Using a Different Launcher?',
},
differentLauncherDescription: {
id: 'servers.play.card.launcher.description',
defaultMessage:
'Install the required content using your preferred launcher, then add the server address in-game to join.',
},
downloadModpackButton: {
id: 'servers.play.card.launcher.download-button',
defaultMessage: 'Download modpack',
},
copyAddress: {
id: 'servers.play.card.address.copy',
defaultMessage: 'Copy server address',
},
copiedAddress: {
id: 'servers.play.card.address.copied',
defaultMessage: 'Server address copied',
},
})

async function copyAddress() {
await navigator.clipboard.writeText(props.address)
copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
}
</script>
Loading
Loading