mirror of
https://github.com/modrinth/code.git
synced 2026-08-28 02:24:56 +00:00
* feat: implement instance share page + search_users backend call * feat: invite players modal * feat: use tanstack queries for friends sync across app pages * feat: base shared instances implementation * fix: admon style * feat: impl instance admonitions like server panel * fix: impl get + del usage * feat: support modpack links * feat: invite notif accepting * fix: lint + fmt * feat: impl install to play * feat: impl usage of UpdateToPlayModal * feat: warnings on deleting/disabling shared-instance version content * fix: send instance name * feat: align with backend * feat: shared instances qa * feat: wrong account protection * feat: qa * fix: smartly apply updates * fix: install bug * fix: 401/404 differentiation * fix: fmt+prepr * feat: qa * feat: qa * fix: signing out messes up revoke/deleted checks * feat: qa * fix: fmt + lint * feat: lock content if part of shared instance * fix: lint * [do not merge] feat: rough invite links impl temp (#6666) * fix: wrong cmd * feat: invite page * fix: server-manager DTO mismatch * fix: drop anonymous invite link acceptance * refactor: structured shared-instance unavailable errors * refactor: centralise error presentations * refactor: dedupe shared instance diff detection * fix: logging in reqwests * refactor: move app.vue shared instances into handler * refactor: break up Share.vue * refactor: split up shared instances state outside of instance index * refactor: dedicated shared instances install/update modals + split up page * refactor: centralized managed content * refactor: split up install shared to own runner + shared.rs split up * refactor: dedupe sql for instance metadata enrichmnt * refactor: friends composable + dedupe friends logic across usages * chore: reduced unused code * fix: align with backend * fix: lint * fix: file sha changes * fix: invite links not working due to icon signed * feat: qa * feat: reporting frontend dummy * fix: try use header * remove: file hash field * fix: pin box * feat: malware warning for shared instances * fix: cache rule * feat: config files syncing * feat: disable config sharing * fix: header * fix: use mark ready * fix: dont cause push update for configs * fix: lint * feat: sharing page in settings * feat: move config + change flow * fix: qa * fix: lint prepr * feat: proxy file upload thru shared instances backend * fix: use collapisible * fix: push config * fix: config * feat: swap out sign in modal for new one * fix: report flow * fix: exclude configs.zip from external warnings * fix: nuxi init * fix: config bundle downloading * fix: error notif * fix: polling * fix: qa * fix: lint + prepr * feat: shared instances moderation frontend + hook up report flow * fix: report copy * fix: lint * fix: lint * fix: modrinth ids being undefined * feat: instance quarantining * fix: prepr + fmt * fix: quarantined -> locked terminology * fix: missing endpoint impls + fmt * fix: missing api in build.rs * fix: share tab jittery * fix: fmt *PT bug * fix: invites count as users even if pending * fix: prepr * fix: invite page owner in users list * fix: lint * fix: qa * fix: lint * fix: members stale not clearing * fix: invite use joined_at field * fix: lint * fix: qa --------- Co-authored-by: sychic <47618543+Sychic@users.noreply.github.com>
213 lines
5.6 KiB
Vue
213 lines
5.6 KiB
Vue
<script setup lang="ts">
|
|
import type { Labrinth } from '@modrinth/api-client'
|
|
import {
|
|
ChevronRightIcon,
|
|
CodeIcon,
|
|
CoffeeIcon,
|
|
InfoIcon,
|
|
MonitorIcon,
|
|
UsersIcon,
|
|
WrenchIcon,
|
|
} from '@modrinth/assets'
|
|
import {
|
|
Avatar,
|
|
commonMessages,
|
|
defineMessage,
|
|
TabbedModal,
|
|
type TabbedModalTab,
|
|
useVIntl,
|
|
} from '@modrinth/ui'
|
|
import type { PlatformTag } from '@modrinth/utils'
|
|
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
|
import { computed, nextTick, ref, watch } from 'vue'
|
|
|
|
import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
|
|
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
|
|
import InstallationSettings from '@/components/ui/instance_settings/InstallationSettings.vue'
|
|
import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
|
|
import SharingSettings from '@/components/ui/instance_settings/SharingSettings.vue'
|
|
import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
|
|
import { get_project_v3 } from '@/helpers/cache'
|
|
import { get_linked_modpack_info } from '@/helpers/instance'
|
|
import { get_loader_versions } from '@/helpers/metadata'
|
|
import { get_game_versions, get_loaders } from '@/helpers/tags'
|
|
import { provideInstanceSettings } from '@/providers/instance-settings'
|
|
|
|
import type { GameInstance } from '../../../helpers/types'
|
|
|
|
const { formatMessage } = useVIntl()
|
|
const queryClient = useQueryClient()
|
|
|
|
const props = defineProps<{
|
|
instance: GameInstance
|
|
offline?: boolean
|
|
}>()
|
|
const emit = defineEmits<{
|
|
unlinked: []
|
|
}>()
|
|
|
|
const isMinecraftServer = ref(false)
|
|
const handleUnlinked = () => emit('unlinked')
|
|
|
|
const instanceRef = computed(() => props.instance)
|
|
const tabbedModal = ref<InstanceType<typeof TabbedModal> | null>(null)
|
|
|
|
function hide() {
|
|
tabbedModal.value?.hide()
|
|
}
|
|
|
|
provideInstanceSettings({
|
|
instance: instanceRef,
|
|
offline: props.offline,
|
|
isMinecraftServer,
|
|
onUnlinked: handleUnlinked,
|
|
closeModal: hide,
|
|
})
|
|
|
|
watch(
|
|
() => props.instance,
|
|
(instance) => {
|
|
isMinecraftServer.value = false
|
|
if (instance.link?.project_id) {
|
|
get_project_v3(instance.link.project_id, 'must_revalidate')
|
|
.then((project: Labrinth.Projects.v3.Project | undefined) => {
|
|
if (project?.minecraft_server != null) {
|
|
isMinecraftServer.value = true
|
|
}
|
|
})
|
|
.catch(() => {})
|
|
}
|
|
},
|
|
{ immediate: true },
|
|
)
|
|
|
|
const tabs = computed<TabbedModalTab[]>(() => [
|
|
{
|
|
name: defineMessage({
|
|
id: 'instance.settings.tabs.general',
|
|
defaultMessage: 'General',
|
|
}),
|
|
icon: InfoIcon,
|
|
content: GeneralSettings,
|
|
},
|
|
{
|
|
name: defineMessage({
|
|
id: 'instance.settings.tabs.installation',
|
|
defaultMessage: 'Installation',
|
|
}),
|
|
icon: WrenchIcon,
|
|
content: InstallationSettings,
|
|
},
|
|
{
|
|
name: defineMessage({
|
|
id: 'instance.settings.tabs.sharing',
|
|
defaultMessage: 'Sharing',
|
|
}),
|
|
icon: UsersIcon,
|
|
content: SharingSettings,
|
|
shown: props.instance.shared_instance?.role === 'owner' && !props.instance.quarantined,
|
|
},
|
|
{
|
|
name: defineMessage({
|
|
id: 'instance.settings.tabs.window',
|
|
defaultMessage: 'Window',
|
|
}),
|
|
icon: MonitorIcon,
|
|
content: WindowSettings,
|
|
},
|
|
{
|
|
name: defineMessage({
|
|
id: 'instance.settings.tabs.java',
|
|
defaultMessage: 'Java and memory',
|
|
}),
|
|
icon: CoffeeIcon,
|
|
content: JavaSettings,
|
|
},
|
|
{
|
|
name: defineMessage({
|
|
id: 'instance.settings.tabs.hooks',
|
|
defaultMessage: 'Launch hooks',
|
|
}),
|
|
icon: CodeIcon,
|
|
content: HooksSettings,
|
|
},
|
|
])
|
|
|
|
function getSupportedModpackLoaders() {
|
|
return get_loaders().then((value: PlatformTag[]) =>
|
|
value
|
|
.filter((item) => item.supported_project_types.includes('modpack') || item.name === 'vanilla')
|
|
.sort((a, b) => (a.name === 'vanilla' ? -1 : b.name === 'vanilla' ? 1 : 0)),
|
|
)
|
|
}
|
|
|
|
// Preload
|
|
useQuery({
|
|
queryKey: ['instance-settings', 'loader-versions', 'fabric'],
|
|
queryFn: () => get_loader_versions('fabric'),
|
|
})
|
|
useQuery({
|
|
queryKey: ['instance-settings', 'loader-versions', 'forge'],
|
|
queryFn: () => get_loader_versions('forge'),
|
|
})
|
|
useQuery({
|
|
queryKey: ['instance-settings', 'loader-versions', 'quilt'],
|
|
queryFn: () => get_loader_versions('quilt'),
|
|
})
|
|
useQuery({
|
|
queryKey: ['instance-settings', 'loader-versions', 'neo'],
|
|
queryFn: () => get_loader_versions('neo'),
|
|
})
|
|
useQuery({
|
|
queryKey: ['instance-settings', 'game-versions'],
|
|
queryFn: get_game_versions,
|
|
})
|
|
useQuery({
|
|
queryKey: ['instance-settings', 'loaders', 'modpack'],
|
|
queryFn: getSupportedModpackLoaders,
|
|
})
|
|
useQuery({
|
|
queryKey: computed(() => ['linkedModpackInfo', props.instance.id]),
|
|
queryFn: () => get_linked_modpack_info(props.instance.id, 'stale_while_revalidate'),
|
|
enabled: computed(() => !!props.instance.link?.project_id && !props.offline),
|
|
})
|
|
|
|
function show(tabIndex?: number) {
|
|
if (props.instance.link?.project_id) {
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['linkedModpackInfo', props.instance.id],
|
|
queryFn: () => get_linked_modpack_info(props.instance.id, 'stale_while_revalidate'),
|
|
})
|
|
}
|
|
tabbedModal.value?.show()
|
|
if (tabIndex !== undefined) {
|
|
nextTick(() => tabbedModal.value?.setTab(tabIndex))
|
|
}
|
|
}
|
|
|
|
defineExpose({ show, hide })
|
|
</script>
|
|
<template>
|
|
<TabbedModal
|
|
ref="tabbedModal"
|
|
:tabs="tabs"
|
|
:max-width="'min(928px, calc(95vw - 10rem))'"
|
|
:width="'min(928px, calc(95vw - 10rem))'"
|
|
>
|
|
<template #title>
|
|
<span class="flex items-center gap-2 text-lg font-semibold text-primary">
|
|
<Avatar
|
|
:src="instance.icon_path ? convertFileSrc(instance.icon_path) : undefined"
|
|
size="24px"
|
|
:tint-by="props.instance.id"
|
|
/>
|
|
{{ instance.name }} <ChevronRightIcon />
|
|
<span class="font-extrabold text-contrast">{{
|
|
formatMessage(commonMessages.settingsLabel)
|
|
}}</span>
|
|
</span>
|
|
</template>
|
|
</TabbedModal>
|
|
</template>
|