mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 09:04:55 +00:00
refactor: content tab styling (#7091)
* refactor: managed content card * fix: update filter pill styling to be chips-like * fix: modpack exporting * fixed: vanilla server projs + header * refactor: filters * refactor: detect external file icons + other metadata inside * refactor: support json5 metadata * fix: qa * fix: qa * fix: fmt + prepr * fix: fmt * fix: qa * fix: headers * feat: locking * fix: clippy * fix: qa * fix: frozen loc * fix: shared instances diff calc break * fix: env filter + remove categories
This commit is contained in:
@@ -140,10 +140,11 @@
|
||||
</div>
|
||||
</NewModal>
|
||||
|
||||
<ModpackContentModal
|
||||
ref="modpackContentModal"
|
||||
:modpack-name="project?.name ?? ''"
|
||||
:modpack-icon-url="project?.icon_url ?? undefined"
|
||||
<ManagedContentModal
|
||||
ref="managedContentModal"
|
||||
:header="formatMessage(messages.modpackContent)"
|
||||
:source-name="project?.name ?? ''"
|
||||
:source-icon-url="project?.icon_url ?? undefined"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -158,7 +159,7 @@ import {
|
||||
type ContentItem,
|
||||
defineMessages,
|
||||
formatLoader,
|
||||
ModpackContentModal,
|
||||
ManagedContentModal,
|
||||
NewModal,
|
||||
Table,
|
||||
type TableColumn,
|
||||
@@ -267,10 +268,10 @@ function handleReport() {
|
||||
}
|
||||
}
|
||||
|
||||
const modpackContentModal = ref<InstanceType<typeof ModpackContentModal>>()
|
||||
const managedContentModal = ref<InstanceType<typeof ManagedContentModal>>()
|
||||
|
||||
async function openViewContents() {
|
||||
modpackContentModal.value?.showLoading()
|
||||
managedContentModal.value?.showLoading()
|
||||
try {
|
||||
// Ensure version data is available — the useQuery may not have resolved yet
|
||||
const versionId = modpackVersionId.value
|
||||
@@ -328,10 +329,10 @@ async function openViewContents() {
|
||||
}
|
||||
},
|
||||
)
|
||||
modpackContentModal.value?.show(contentItems)
|
||||
managedContentModal.value?.show(contentItems)
|
||||
} catch (err) {
|
||||
console.error('Failed to load modpack contents:', err)
|
||||
modpackContentModal.value?.show([])
|
||||
managedContentModal.value?.show([])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +361,10 @@ function hide() {
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
modpackContent: {
|
||||
id: 'app.modal.install-to-play.managed-content.modpack-header',
|
||||
defaultMessage: 'Modpack content',
|
||||
},
|
||||
installToPlay: {
|
||||
id: 'app.modal.install-to-play.header',
|
||||
defaultMessage: 'Install to play',
|
||||
|
||||
+5
-5
@@ -229,11 +229,11 @@
|
||||
</div>
|
||||
</template>
|
||||
</NewModal>
|
||||
<ModpackContentModal
|
||||
<ManagedContentModal
|
||||
ref="contentModal"
|
||||
:header="formatMessage(messages.sharedInstanceContent)"
|
||||
:modpack-name="preview?.name ?? ''"
|
||||
:modpack-icon-url="preview?.iconUrl ?? undefined"
|
||||
:source-name="preview?.name ?? ''"
|
||||
:source-icon-url="preview?.iconUrl ?? undefined"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -255,8 +255,8 @@ import {
|
||||
injectModrinthClient,
|
||||
injectNotificationManager,
|
||||
IntlFormatted,
|
||||
ManagedContentModal,
|
||||
MarkdownEditor,
|
||||
ModpackContentModal,
|
||||
NewModal,
|
||||
Table,
|
||||
type TableColumn,
|
||||
@@ -288,7 +288,7 @@ type SharedInstanceCreator = {
|
||||
}
|
||||
|
||||
const modal = ref<InstanceType<typeof NewModal>>()
|
||||
const contentModal = ref<InstanceType<typeof ModpackContentModal>>()
|
||||
const contentModal = ref<InstanceType<typeof ManagedContentModal>>()
|
||||
const externalFileTable = ref<HTMLElement | null>(null)
|
||||
const preview = ref<SharedInstanceInstallPreview | null>(null)
|
||||
const creator = ref<SharedInstanceCreator | null>(null)
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
import type {
|
||||
ContentItem,
|
||||
ContentModpackCardCategory,
|
||||
ContentModpackCardProject,
|
||||
ContentModpackCardVersion,
|
||||
ContentOwner,
|
||||
} from '@modrinth/ui'
|
||||
import type { ContentItem, ManagedContentProject, ManagedContentVersion } from '@modrinth/ui'
|
||||
|
||||
import {
|
||||
get_content_items,
|
||||
get_linked_modpack_info,
|
||||
type LinkedModpackInfo,
|
||||
} from '@/helpers/instance'
|
||||
import { get_categories } from '@/helpers/tags.js'
|
||||
import type { CacheBehaviour } from '@/helpers/types'
|
||||
|
||||
export type InstanceContentData = {
|
||||
@@ -21,11 +14,8 @@ export type InstanceContentData = {
|
||||
}
|
||||
|
||||
export type InstanceContentModpackData = {
|
||||
project: ContentModpackCardProject
|
||||
version: ContentModpackCardVersion
|
||||
owner: ContentOwner | null
|
||||
categories: ContentModpackCardCategory[]
|
||||
hasUpdate: boolean
|
||||
project: ManagedContentProject
|
||||
version: ManagedContentVersion
|
||||
updateVersionId: string | null
|
||||
}
|
||||
|
||||
@@ -34,19 +24,15 @@ export async function loadInstanceContentData(
|
||||
cacheBehaviour?: CacheBehaviour,
|
||||
onError?: (error: Error) => unknown,
|
||||
): Promise<InstanceContentData> {
|
||||
const [contentItems, modpackInfo, allCategories] = await Promise.all([
|
||||
const [contentItems, modpackInfo] = await Promise.all([
|
||||
get_content_items(path, cacheBehaviour).catch((error) => handleLoadError(error, onError)),
|
||||
get_linked_modpack_info(path, cacheBehaviour).catch((error) => handleLoadError(error, onError)),
|
||||
get_categories().catch((error) => handleLoadError(error, onError)),
|
||||
])
|
||||
|
||||
return {
|
||||
path,
|
||||
contentItems: (contentItems as ContentItem[] | null | undefined) ?? null,
|
||||
modpack: normalizeLinkedModpackInfo(
|
||||
modpackInfo as LinkedModpackInfo | null | undefined,
|
||||
allCategories as ContentModpackCardCategory[] | null | undefined,
|
||||
),
|
||||
modpack: normalizeLinkedModpackInfo(modpackInfo as LinkedModpackInfo | null | undefined),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +44,6 @@ function handleLoadError(error: unknown, onError?: (error: Error) => unknown) {
|
||||
|
||||
function normalizeLinkedModpackInfo(
|
||||
modpackInfo: LinkedModpackInfo | null | undefined,
|
||||
allCategories: ContentModpackCardCategory[] | null | undefined,
|
||||
): InstanceContentModpackData | null {
|
||||
if (!modpackInfo) return null
|
||||
|
||||
@@ -72,30 +57,6 @@ function normalizeLinkedModpackInfo(
|
||||
...modpackInfo.version,
|
||||
date_published: modpackInfo.version.date_published.toString(),
|
||||
},
|
||||
owner: modpackInfo.owner
|
||||
? {
|
||||
...modpackInfo.owner,
|
||||
avatar_url: modpackInfo.owner.avatar_url ?? undefined,
|
||||
}
|
||||
: null,
|
||||
categories: resolveLinkedModpackCategories(modpackInfo, allCategories),
|
||||
hasUpdate: modpackInfo.has_update,
|
||||
updateVersionId: modpackInfo.update_version_id,
|
||||
}
|
||||
}
|
||||
|
||||
function resolveLinkedModpackCategories(
|
||||
modpackInfo: LinkedModpackInfo,
|
||||
allCategories: ContentModpackCardCategory[] | null | undefined,
|
||||
) {
|
||||
if (!allCategories || !modpackInfo.project.categories) return []
|
||||
|
||||
const seen = new Set<string>()
|
||||
return allCategories.filter((category) => {
|
||||
if (modpackInfo.project.categories.includes(category.name) && !seen.has(category.name)) {
|
||||
seen.add(category.name)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import type { ContentItem, ContentOwner } from '@modrinth/ui'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { convertFileSrc, invoke } from '@tauri-apps/api/core'
|
||||
|
||||
import type { InstallJobSnapshot, SharedInstanceUpdateDiff } from './install'
|
||||
import type {
|
||||
@@ -74,7 +74,11 @@ export async function get_content_items(
|
||||
instanceId: string,
|
||||
cacheBehaviour?: CacheBehaviour,
|
||||
): Promise<ContentItem[]> {
|
||||
return await invoke('plugin:instance|instance_get_content_items', { instanceId, cacheBehaviour })
|
||||
const items = await invoke<ContentItem[]>('plugin:instance|instance_get_content_items', {
|
||||
instanceId,
|
||||
cacheBehaviour,
|
||||
})
|
||||
return adaptContentItems(items)
|
||||
}
|
||||
|
||||
export async function refresh_content_updates(instanceId: string): Promise<void> {
|
||||
@@ -111,10 +115,11 @@ export async function get_linked_modpack_content(
|
||||
instanceId: string,
|
||||
cacheBehaviour?: CacheBehaviour,
|
||||
): Promise<ContentItem[]> {
|
||||
return await invoke('plugin:instance|instance_get_linked_modpack_content', {
|
||||
const items = await invoke<ContentItem[]>('plugin:instance|instance_get_linked_modpack_content', {
|
||||
instanceId,
|
||||
cacheBehaviour,
|
||||
})
|
||||
return adaptContentItems(items)
|
||||
}
|
||||
|
||||
// Convert a list of dependencies into ContentItems with rich metadata
|
||||
@@ -122,9 +127,28 @@ export async function get_dependencies_as_content_items(
|
||||
dependencies: Labrinth.Versions.v3.Dependency[],
|
||||
cacheBehaviour?: CacheBehaviour,
|
||||
): Promise<ContentItem[]> {
|
||||
return await invoke('plugin:instance|instance_get_dependencies_as_content_items', {
|
||||
dependencies,
|
||||
cacheBehaviour,
|
||||
const items = await invoke<ContentItem[]>(
|
||||
'plugin:instance|instance_get_dependencies_as_content_items',
|
||||
{
|
||||
dependencies,
|
||||
cacheBehaviour,
|
||||
},
|
||||
)
|
||||
return adaptContentItems(items)
|
||||
}
|
||||
|
||||
function adaptContentItems(items: ContentItem[]): ContentItem[] {
|
||||
return items.map((item) => {
|
||||
const embeddedMetadata = item.embedded_metadata
|
||||
if (!embeddedMetadata?.icon_path) return item
|
||||
|
||||
return {
|
||||
...item,
|
||||
embedded_metadata: {
|
||||
...embeddedMetadata,
|
||||
icon_url: convertFileSrc(embeddedMetadata.icon_path),
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -264,6 +288,18 @@ export async function toggle_disable_project(
|
||||
})
|
||||
}
|
||||
|
||||
export async function set_project_locked(
|
||||
instanceId: string,
|
||||
projectPath: string,
|
||||
locked: boolean,
|
||||
): Promise<void> {
|
||||
return await invoke('plugin:instance|instance_set_project_locked', {
|
||||
instanceId,
|
||||
projectPath,
|
||||
locked,
|
||||
})
|
||||
}
|
||||
|
||||
// Remove a project
|
||||
export async function remove_project(instanceId: string, projectPath: string): Promise<void> {
|
||||
return await invoke('plugin:instance|instance_remove_project', { instanceId, projectPath })
|
||||
|
||||
+1
@@ -128,6 +128,7 @@ export type ContentSourceKind =
|
||||
|
||||
type ContentFile = {
|
||||
enabled: boolean
|
||||
locked: boolean
|
||||
source_kind?: ContentSourceKind | null
|
||||
metadata?: {
|
||||
project_id: string
|
||||
|
||||
@@ -1073,16 +1073,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "مزامنة مع النسخة"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "يقدمها الخادم"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "يمكن إضافة التعديلات **المحليه** فقط إلى نموذج الخادم"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "يتم توفير نسخة اللعبة من قبل الخادم"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "يتم توفير المحمّل من قبل الخادم"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,16 +965,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synchronizováno s instancí"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Poskytováno serverem"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Pouze módy ze strany klientu mohou být přidány na server"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Verze hry je poskytována serverem"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader zprostředkovává server"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,18 +296,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Gennemså ændringer"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Gennemgå opdatering"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Gennemgår..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "En opdatering er krævet for at spille {name}. Venligst opdater til den seneste version for at køre spillet."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "En opdatering er tilgængelig"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Al' data for din instance vil blive permanent slettet, dette inkludere dine verdener, konfigurationer, og alt installeret indhold."
|
||||
},
|
||||
@@ -1181,16 +1172,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synkroniser med instance"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Givet af serveren"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Kun klient-sided mods kan blive tilføjet til denne server instance"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Spille version er givet af serveren"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader er givet af serveren"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Änderungen überprüfen"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Update überprüfen"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Wird überprüft..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Ein Update ist erforderlich, um {name} zu spielen. Bitte aktualisiere auf die neueste Version, um das Spiel zu starten."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Ein Update ist verfügbar"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Alle Daten deiner Instanz werden permanent gelöscht, inlusive deiner Welten, Konfigurationen und allen installierten Inhalten."
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Mit Instanz synchronisieren"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Vom Server bereitgestellt"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Nur Clientseitige Mods können der Serverinstanz hinzugefügt werden"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Spielversion wird vom Server bereitgestellt"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader wird vom Server bereitgestellt"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Konto"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Änderungen überprüfen"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Update überprüfen"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Wird überprüft..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Ein Update ist erforderlich, um {name} zu spielen. Bitte aktualisiere auf die neueste Version, um das Spiel zu starten."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Ein Update ist verfügbar"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Alle Daten deiner Instanz werden permanent gelöscht, einschließlich deiner Welten, Konfigurationen und allen installierten Inhalten."
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Mit Instanz synchronisieren"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Vom Server vorgegeben"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Nur clientseitige Mods können der Serverinstanz hinzugefügt werden"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Spielversion vom Server vorgegeben"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader vom Server vorgegeben"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Konto"
|
||||
},
|
||||
|
||||
@@ -273,7 +273,7 @@
|
||||
"message": "Modpacks"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Adding content can break compatibility when joining the server. Any added content will also be lost when you update the server instance content."
|
||||
"message": "Adding content may prevent you from joining this server. Any content you add will be removed when the managed server content is updated."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Installing"
|
||||
@@ -395,18 +395,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Review changes"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Review update"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Reviewing..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "An update is required to play {name}. Please update to latest version to launch the game."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "An update is available"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "All data for your instance will be permanently deleted, including your worlds, configs, and all installed content."
|
||||
},
|
||||
@@ -419,6 +410,12 @@
|
||||
"app.instance.confirm-delete.header": {
|
||||
"message": "Delete instance"
|
||||
},
|
||||
"app.instance.content.managed-content.modpack-header": {
|
||||
"message": "Modpack content"
|
||||
},
|
||||
"app.instance.content.managed-content.shared-header": {
|
||||
"message": "Shared content"
|
||||
},
|
||||
"app.instance.modpack-already-installed.body": {
|
||||
"message": "This modpack is already installed in the <bold>{instanceName}</bold> instance. Are you sure you want to duplicate it?"
|
||||
},
|
||||
@@ -443,6 +440,9 @@
|
||||
"app.instance.mods.content-type-project": {
|
||||
"message": "project"
|
||||
},
|
||||
"app.instance.mods.freeze-content": {
|
||||
"message": "Freeze version"
|
||||
},
|
||||
"app.instance.mods.locked-content": {
|
||||
"message": "Content in locked instances cannot be changed."
|
||||
},
|
||||
@@ -461,6 +461,9 @@
|
||||
"app.instance.mods.successfully-uploaded": {
|
||||
"message": "Successfully uploaded"
|
||||
},
|
||||
"app.instance.mods.unfreeze-content": {
|
||||
"message": "Unfreeze version"
|
||||
},
|
||||
"app.instance.share.empty.description": {
|
||||
"message": "You can share this instance with your friends!"
|
||||
},
|
||||
@@ -704,6 +707,9 @@
|
||||
"app.modal.install-to-play.invite-warning-with-creator": {
|
||||
"message": "This invite was created by <creator>{username}</creator>, not Modrinth. Only accept invites from people you trust."
|
||||
},
|
||||
"app.modal.install-to-play.managed-content.modpack-header": {
|
||||
"message": "Modpack content"
|
||||
},
|
||||
"app.modal.install-to-play.mod-count": {
|
||||
"message": "{count, plural, one {# mod} other {# mods}}"
|
||||
},
|
||||
@@ -1475,6 +1481,9 @@
|
||||
"instance.files.save-as": {
|
||||
"message": "Save as..."
|
||||
},
|
||||
"instance.last-played": {
|
||||
"message": "Last played"
|
||||
},
|
||||
"instance.locked.delete-button": {
|
||||
"message": "Delete instance"
|
||||
},
|
||||
@@ -1940,18 +1949,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sync with instance"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Provided by the server"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Only client-side mods can be added to the server instance"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Game version is provided by the server"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader is provided by the server"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Account"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Revisar cambios"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Actualizar"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Actualizando..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Se necesita una actualización para jugar a {name}. Por favor actualiza a la versión más reciente para iniciar el juego."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Hay una actualización disponible"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Todos los datos de tu instancia se eliminarán permanentemente, incluidos tus mundos, configuraciones y todo el contenido instalado."
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sincronizar con la instancia"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Proporcionado por el servidor"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Solo se pueden añadir mods que sean del lado del cliente a la instancia del servidor"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "La versión del juego es proporcionada por el servidor"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "El loader es proporcionado por el servidor"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Cuenta"
|
||||
},
|
||||
|
||||
@@ -878,16 +878,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sincronizar con la instancia"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Proporcionado por el servidor"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Solo se pueden añadir a la instancia del servidor modificaciones del lado del cliente"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "La versión del juego es proporcionada por el servidor"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader proporcionado por el servidor"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,16 +959,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synkronoi instanssin kanssa"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Palvelimen tarjoama"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Voit lisätä vain paikallisia modeja palvelin instanssiin"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Peliversio on palvelimen tarjoama"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Modialusta on palvelimen tarjoama"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,16 +659,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Maki-sync sa instansiya"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Handog ng server"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Mga mod sa panig ng client lamang ang maidadaragdag sa instansiyang server"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Ang bersiyon ng laro ay handog ng server"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Ang loader ay handog na ng server"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Examiner les modifications"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Télécharger la mise à jour"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Examination..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Une mise à jour est nécessaire pour jouer à {name}. Veuillez mettre à jour vers la dernière version pour lancer le jeu."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Une mise à jour est disponible"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Toutes les données pour votre instance seront supprimées à jamais, y compris vos mondes, vos configurations, et le contenu installé."
|
||||
},
|
||||
@@ -1919,18 +1910,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synchroniser avec l'instance"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Fournis par le serveur"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Seuls les mods client peuvent être ajoutés à l'instance du serveur"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Version du jeu est procurée par le serveur"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Le loader est procuré par le serveur"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Compte"
|
||||
},
|
||||
|
||||
@@ -533,16 +533,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "סנכרן עם התקנה"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "מסופק על ידי השרת"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "ניתן להוסיף רק מודים בצד הלקוח לשרת"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "גרסת המשחק מסופקת על ידי השרת"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "הטוען מסופק על ידי השרת"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Változtatások áttekintése"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Frissítés áttekintése"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Áttekintés..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Egy frssítés szükséges a(z) {name} példányhoz. Kérjük, frissítsd a játékot a legújabb verzióra az indításhoz."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Frissítés érhető el"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "A példányodhoz tartozó összes adat véglegesen törlődik, beleértve a világjaidat, a beállításaidat és az összes telepített tartalmat."
|
||||
},
|
||||
@@ -1907,18 +1898,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Szinkronizálás a példánnyal"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "A szerver által van megadva"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Szerverpéldányokhoz csak szerveroldali modok adhatók hozzá"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "A játékverzió a szerver által van megadva"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "A betöltőt az adott szerver biztosítja"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Fiók"
|
||||
},
|
||||
|
||||
@@ -821,16 +821,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sinkronkan dengan instans"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Disediakan oleh server"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Anda hanya dapat menambahkan mod sisi klien pada instans server"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Versi permainan disediakan oleh server"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Pemuat disediakan oleh server"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Revisiona modifiche"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Revisiona aggiornamento"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Revisione..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "{name} richiede degli aggiornamenti. Installa l'ultima versione per poter giocare."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Aggiornamento disponibile"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Tutti i dati della tua istanza verranno eliminati permanentemente, inclusi i tuoi mondi, configurazioni e tutti i contenuti installati."
|
||||
},
|
||||
@@ -1919,18 +1910,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sincronizza con l'istanza"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Determinato dal server"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Solo mod lato client possono essere aggiunte all'istanza del server"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "La versione del gioco è determinata dal server"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Il loader è determinato dal server"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Account"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "変更点を確認"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "アップデート内容を確認"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "審査中…"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "{name}をプレイするにはアップデートが必要です。ゲームを起動するには最新バージョンにアップデートしてください。"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "アップデートが利用可能です"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "インスタンス内のすべてのデータは、ワールド、設定、インストール済みのコンテンツを含め、完全に削除されます。"
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "インスタンスと同期"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "サーバーによる条件"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "サーバーインスタンスにはクライアント側Modのみ追加可能"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "ゲームバージョンはサーバーによる条件です"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "ローダーはサーバーによる条件です"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "アカウント"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Review changes"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "업데이트 검토"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "검토중..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "{name} 플레이를 위해 업데이트가 필요합니다. 게임을 실행하려면 최신 버전 업데이트를 진행하세요."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "업데이트가 있습니다"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "인스턴스의 모든 데이터가 삭제됩니다. 세계 폴더, 설정 폴더 등 설치된 모든 컨텐츠가 포함됩니다."
|
||||
},
|
||||
@@ -1895,18 +1886,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "인스턴스와 동기화"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "서버에 의해 관리됨"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "서버 인스턴스에는 클라이언트 전용 모드만 추가할 수 있습니다"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "게임 버전이 서버에 의해 제공됩니다"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "로더가 서버에 의해 제공됩니다"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "계정"
|
||||
},
|
||||
|
||||
@@ -818,16 +818,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Selaraskan dengan pemasangan"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Disediakan oleh pelayan"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Hanya mod bahagian pelanggan sahaja yang boleh ditambah pada pemasangan pelayan"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Versi permainan adalah disediakan oleh pelayan"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Pemuat adalah disediakan oleh pelayan"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Wijzigingen bekijken"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Update bekijken"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Controleren..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Er is een update nodig om {name} te kunnen spelen. Werk het spel bij naar de nieuwste versie om het te kunnen starten."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Update is beschikbaar"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Alle gegevens van je instantie worden definitief verwijderd, inclusief je werelden, configuraties en alle geïnstalleerde inhoud."
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synchroniseer installatie"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Aangeleverd door de server"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Alleen client-side mods kunnen toegevoegd worden aan de server instantie"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Spel versie is gegeven door de server"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader is gegeven door de server"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Account"
|
||||
},
|
||||
|
||||
@@ -371,15 +371,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Sprawdź zmiany"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Sprawdź aktualizację"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Trwa przegląd..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Dostępna aktualizacja"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Wszystkie dane z Twojej instancji zostaną trwale usunięte, w tym Twoje światy, pliki konfiguracji i jakakolwiek dodana zawartość."
|
||||
},
|
||||
@@ -1703,18 +1697,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synchronizuj z instancją"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Dostarczone przez serwer"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Tylko mody po stronie klienta mogą być dodane do instancji serwera"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Wersja gry jest dostarczona przez serwer"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader jest dostarczony przez serwer"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Konto"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Revisar alterações"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Revisar atualização"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Revisando..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Uma atualização é necessária para jogar {name}. Atualize para a versão mais recente para iniciar o jogo."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Uma atualização está disponível"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Todos os dados para sua instância serão excluídos permanentemente, incluindo seus mundos, configs e todo o conteúdo instalado."
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sincronizar com a instância"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Fornecido pelo servidor"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Somente mods do cliente podem ser adicionados à instância do servidor"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "A versão do jogo é fornecida pelo servidor"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "O loader é fornecido pelo servidor"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Conta"
|
||||
},
|
||||
|
||||
@@ -872,16 +872,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sincronizar com a instância"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Fornecido pelo servidor"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Apenas mods no cliente podem ser adicionados à instância de servidor"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Versão do jogo é fornecida pelo servidor"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Carregador é fornecido pelo servidor"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,16 +506,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sincronizează cu instanța"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Furnizat de server"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Numai modurile de pe partea clientului pot fi adăugate la instanța serverului"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Versiunea jocului este furnizată de server"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Încărcătorul este furnizat de server"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Проверьте изменения"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Обзор обновления"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Проверка..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Необходимо обновление для игры в {name}. Обновитесь до последней версии и запустите игру."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Доступно обновление"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Все данные сборки будут удалены навсегда, в том числе миры, настройки и весь установленный контент."
|
||||
},
|
||||
@@ -1910,18 +1901,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Использовать из сборки"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Управляется сервером"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "В серверной сборке доступны только клиентские моды"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Версия игры управляется сервером"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Загрузчик управляется сервером"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Аккаунт"
|
||||
},
|
||||
|
||||
@@ -1100,16 +1100,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Sinhroniziraj sa instancom"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Obezbeđeno od servera"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Samo modovi za kliente mogu biti dodani na instancu servera"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Verzije igre je obezbeđena od servera"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Učitavač je obezbeđen od servera"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,18 +359,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Granskar ändringar"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Granska uppdatering"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Granskar..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "En uppdatering krävs för att spela {name}. Vänligen uppdatera till den senaste verisoner för att köra spelet."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "En uppdatering finns tillgänglig"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "All data från din instans kommer permanent raderas, däribland dina världar, konfigurationer samt allt installerat innehåll."
|
||||
},
|
||||
@@ -1718,18 +1709,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Synkronisera med instansen"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Tillhandahållet av servern"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Endast klient-sido moddar kan läggas till i serverinstansen"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Spelversion tillhandahålls av servern"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader tillhandahålls av servern"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Konto"
|
||||
},
|
||||
|
||||
@@ -785,16 +785,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "เชื่อมต่อกับโปรแกรม"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "เซิร์ฟเวอร์เป็นผู้กำหนด"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "มีเพียงม็อดสำหรับฝั่งเครื่องของผู้เล่นเท่านั้นที่สามารถเพิ่มลงในโปรแกรมเซิร์ฟเวอร์ดังกล่าวได้"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "เวอร์ชันเกมถูกกำหนดโดยเซิร์ฟเวอร์แล้ว"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "ตัวรันถูกกำหนดโดยเซิร์ฟเวอร์แล้ว"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Değişimleri inceleniyor"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Güncellemeyi gözden geçir"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "İnceleniyor..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "{name}'i oynamak için bir güncelleme gerekli. Oyunu açabilmek için lütfen son sürüme güncelleyin."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Bir güncelleme mevcut"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Dünyalarınız, yapılandırmalarınız ve yüklü tüm içerikler ve tüm veriler kalıcı olarak silinecek."
|
||||
},
|
||||
@@ -1508,18 +1499,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Kurulum ile eşitle"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Sunucu tarafından sağlanmıştır"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Sunucu örneğine yalnızca istemci tarafında çalışan modlar eklenebilir"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Oyun sürümü sunucu tarafından sağlanıyor"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Yükleyici sunucu tarafından sağlanıyor"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Hesap"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "Огляд змін"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "Переглянути оновлення"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "Оглядаємо…"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "Для гри в {name} потрібне оновлення. Будь ласка, оновіть до найновішої версії, щоб запустити гру."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "Доступне оновлення"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Усі дані вашого профілю будуть видалені назавжди, включно з вашими світами, налаштуваннями та всім установленим умістом."
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Синхронізувати з профілем"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Надано сервером"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "До профілю сервера можна додавати лише клієнтські моди"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Версія гри надана сервером"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Завантажувач наданий сервером"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "Обліковий запис"
|
||||
},
|
||||
|
||||
@@ -998,16 +998,7 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Đồng bộ với phiên bản"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "Do máy chủ cung cấp"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "Chỉ các mod chạy phía client mới có thể thêm hồ sơ máy chủ"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "Phiên bản trò chơi được cung cấp bởi máy chủ"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader được cung cấp bởi máy chủ"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "查看变更"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "查看更新"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "正在审查……"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "{name}需要更新。请更新到最新版本以启动游戏。"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "有更新可用"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "你实例的所有数据将被永久删除,包括你的世界、配置和所有已安装的内容。"
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "与实例同步"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "由该服务器提供"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "只能将客户端模组添加到服务器实例中"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "游戏版本由服务器提供"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "加载器由服务器提供"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "账户"
|
||||
},
|
||||
|
||||
@@ -377,18 +377,9 @@
|
||||
"app.instance.admonitions.shared-instance.review-header": {
|
||||
"message": "檢視變更"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.review-update-button": {
|
||||
"message": "檢視更新"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.reviewing-button": {
|
||||
"message": "正在檢視..."
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-body": {
|
||||
"message": "需要更新才能遊玩「{name}」。請更新至最新版本以啟動遊戲。"
|
||||
},
|
||||
"app.instance.admonitions.shared-instance.update-available-header": {
|
||||
"message": "有可用的更新"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "你實例中的所有資料將被永久刪除,包含你的世界、設定檔以及所有已安裝的內容。"
|
||||
},
|
||||
@@ -1922,18 +1913,9 @@
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "與實例同步"
|
||||
},
|
||||
"search.filter.locked.server": {
|
||||
"message": "由伺服器提供"
|
||||
},
|
||||
"search.filter.locked.server-environment.title": {
|
||||
"message": "只有用戶端模組可以被加到伺服器實例"
|
||||
},
|
||||
"search.filter.locked.server-game-version.title": {
|
||||
"message": "遊戲版本由伺服器提供"
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "載入器由伺服器提供"
|
||||
},
|
||||
"settings.sidebar.label.account": {
|
||||
"message": "帳號"
|
||||
},
|
||||
|
||||
@@ -399,9 +399,10 @@ const hideInstalledModpacks = computed({
|
||||
const instanceFilters = computed(() => {
|
||||
const filters = []
|
||||
|
||||
if (instance.value) {
|
||||
if (instance.value && projectType.value !== 'resourcepack') {
|
||||
const isVanillaShader = projectType.value === 'shader' && instance.value.loader === 'vanilla'
|
||||
const gameVersion = instance.value.game_version
|
||||
if (gameVersion) {
|
||||
if (gameVersion && !isVanillaShader) {
|
||||
filters.push({ type: 'game_version', option: gameVersion })
|
||||
}
|
||||
|
||||
@@ -411,6 +412,9 @@ const instanceFilters = computed(() => {
|
||||
if (platform && projectType.value === 'mod' && supportedModLoaders.includes(platform)) {
|
||||
filters.push({ type: 'mod_loader', option: platform })
|
||||
}
|
||||
if (isVanillaShader) {
|
||||
filters.push({ type: 'shader_loader', option: 'vanilla' })
|
||||
}
|
||||
|
||||
if (isServerInstance.value) {
|
||||
filters.push({ type: 'environment', option: 'client' })
|
||||
@@ -550,10 +554,6 @@ const messages = defineMessages({
|
||||
id: 'search.filter.locked.instance-game-version.title',
|
||||
defaultMessage: 'Game version is provided by the instance',
|
||||
},
|
||||
gameVersionProvidedByServer: {
|
||||
id: 'search.filter.locked.server-game-version.title',
|
||||
defaultMessage: 'Game version is provided by the server',
|
||||
},
|
||||
hideAddedServers: {
|
||||
id: 'app.browse.hide-added-servers',
|
||||
defaultMessage: 'Hide servers already added',
|
||||
@@ -573,7 +573,7 @@ const messages = defineMessages({
|
||||
serverInstanceContentWarning: {
|
||||
id: 'app.browse.server-instance-content-warning',
|
||||
defaultMessage:
|
||||
'Adding content can break compatibility when joining the server. Any added content will also be lost when you update the server instance content.',
|
||||
'Adding content may prevent you from joining this server. Any content you add will be removed when the managed server content is updated.',
|
||||
},
|
||||
modLoaderProvidedByInstance: {
|
||||
id: 'search.filter.locked.instance-loader.title',
|
||||
@@ -583,18 +583,10 @@ const messages = defineMessages({
|
||||
id: 'app.browse.project-type.modpacks',
|
||||
defaultMessage: 'Modpacks',
|
||||
},
|
||||
modLoaderProvidedByServer: {
|
||||
id: 'search.filter.locked.server-loader.title',
|
||||
defaultMessage: 'Loader is provided by the server',
|
||||
},
|
||||
providedByInstance: {
|
||||
id: 'search.filter.locked.instance',
|
||||
defaultMessage: 'Provided by the instance',
|
||||
},
|
||||
providedByServer: {
|
||||
id: 'search.filter.locked.server',
|
||||
defaultMessage: 'Provided by the server',
|
||||
},
|
||||
syncFilterButton: {
|
||||
id: 'search.filter.locked.instance.sync',
|
||||
defaultMessage: 'Sync with instance',
|
||||
@@ -743,7 +735,7 @@ const installContext = computed(() => {
|
||||
isFromWorlds.value ? messages.addServersToInstance : commonMessages.installingContentLabel,
|
||||
),
|
||||
warning:
|
||||
isServerInstance.value && !isFromWorlds.value
|
||||
isServerInstance.value && instance.value.loader !== 'vanilla' && !isFromWorlds.value
|
||||
? formatMessage(messages.serverInstanceContentWarning)
|
||||
: undefined,
|
||||
}
|
||||
@@ -1106,24 +1098,12 @@ async function search(requestParams: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const isServerFilterContext = computed(() => isServerContext.value || isServerInstance.value)
|
||||
|
||||
const lockedFilterMessages = computed(() => ({
|
||||
gameVersion: formatMessage(
|
||||
isServerFilterContext.value
|
||||
? messages.gameVersionProvidedByServer
|
||||
: messages.gameVersionProvidedByInstance,
|
||||
),
|
||||
modLoader: formatMessage(
|
||||
isServerFilterContext.value
|
||||
? messages.modLoaderProvidedByServer
|
||||
: messages.modLoaderProvidedByInstance,
|
||||
),
|
||||
gameVersion: formatMessage(messages.gameVersionProvidedByInstance),
|
||||
modLoader: formatMessage(messages.modLoaderProvidedByInstance),
|
||||
environment: formatMessage(messages.environmentProvidedByServer),
|
||||
syncButton: formatMessage(messages.syncFilterButton),
|
||||
providedBy: formatMessage(
|
||||
isServerFilterContext.value ? messages.providedByServer : messages.providedByInstance,
|
||||
),
|
||||
providedBy: formatMessage(messages.providedByInstance),
|
||||
}))
|
||||
|
||||
const searchState = useBrowseSearch({
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
:instance="instance"
|
||||
@published="emit('published')"
|
||||
/>
|
||||
<InstanceAdmonitionsSharedInstanceUpdateAvailable
|
||||
v-else-if="item.kind === 'shared-instance-update-available'"
|
||||
:instance-name="instance.name"
|
||||
@review="emit('review-update', $event)"
|
||||
/>
|
||||
<InstanceAdmonitionsSharedInstanceWrongAccount
|
||||
v-else-if="item.kind === 'shared-instance-wrong-account'"
|
||||
:expected-user-id="sharedInstanceExpectedUserId"
|
||||
@@ -38,7 +33,6 @@ import type { GameInstance } from '@/helpers/types'
|
||||
|
||||
import InstanceAdmonitionsSharedInstanceStale from './shared-instance-stale.vue'
|
||||
import InstanceAdmonitionsSharedInstanceUnavailable from './shared-instance-unavailable.vue'
|
||||
import InstanceAdmonitionsSharedInstanceUpdateAvailable from './shared-instance-update-available.vue'
|
||||
import InstanceAdmonitionsSharedInstanceWrongAccount from './shared-instance-wrong-account.vue'
|
||||
import type { InstanceAdmonitionItem, SharedInstanceRole } from './types.ts'
|
||||
|
||||
@@ -54,13 +48,11 @@ const props = defineProps<{
|
||||
sharedInstanceExpectedUserId?: string | null
|
||||
sharedInstanceRole?: SharedInstanceRole | null
|
||||
sharedInstanceSignedOut?: boolean
|
||||
sharedInstanceUpdateAvailable?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
published: []
|
||||
delete: []
|
||||
'review-update': [event: MouseEvent]
|
||||
}>()
|
||||
|
||||
const sharedInstanceWrongAccount = computed(() => props.sharedInstanceWrongAccount ?? false)
|
||||
@@ -76,15 +68,6 @@ const showSharedInstancePublishAdmonition = computed(
|
||||
props.instance.shared_instance?.role === 'owner' &&
|
||||
props.instance.shared_instance.status === 'stale',
|
||||
)
|
||||
const showSharedInstanceUpdateAdmonition = computed(
|
||||
() =>
|
||||
!sharedInstanceWrongAccount.value &&
|
||||
!displayedSharedInstanceUnavailableReason.value &&
|
||||
props.instance.install_stage === 'installed' &&
|
||||
props.sharedInstanceRole === 'member' &&
|
||||
props.sharedInstanceUpdateAvailable === true,
|
||||
)
|
||||
|
||||
const stackItems = computed<InstanceAdmonitionItem[]>(() => {
|
||||
const items: InstanceAdmonitionItem[] = []
|
||||
|
||||
@@ -120,15 +103,6 @@ const stackItems = computed<InstanceAdmonitionItem[]>(() => {
|
||||
})
|
||||
}
|
||||
|
||||
if (showSharedInstanceUpdateAdmonition.value) {
|
||||
items.push({
|
||||
id: 'shared-instance-update-available',
|
||||
type: 'info',
|
||||
dismissible: false,
|
||||
kind: 'shared-instance-update-available',
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
})
|
||||
|
||||
|
||||
@@ -21,19 +21,6 @@ export const instanceAdmonitionsMessages = defineMessages({
|
||||
id: 'app.instance.admonitions.shared-instance.reviewing-button',
|
||||
defaultMessage: 'Reviewing...',
|
||||
},
|
||||
sharedInstanceUpdateAvailableHeader: {
|
||||
id: 'app.instance.admonitions.shared-instance.update-available-header',
|
||||
defaultMessage: 'An update is available',
|
||||
},
|
||||
sharedInstanceUpdateAvailableBody: {
|
||||
id: 'app.instance.admonitions.shared-instance.update-available-body',
|
||||
defaultMessage:
|
||||
'An update is required to play {name}. Please update to latest version to launch the game.',
|
||||
},
|
||||
sharedInstanceReviewUpdateButton: {
|
||||
id: 'app.instance.admonitions.shared-instance.review-update-button',
|
||||
defaultMessage: 'Review update',
|
||||
},
|
||||
sharedInstanceReviewHeader: {
|
||||
id: 'app.instance.admonitions.shared-instance.review-header',
|
||||
defaultMessage: 'Review changes',
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<Admonition
|
||||
type="info"
|
||||
inline-actions
|
||||
:header="formatMessage(messages.sharedInstanceUpdateAvailableHeader)"
|
||||
>
|
||||
{{ formatMessage(messages.sharedInstanceUpdateAvailableBody, { name: instanceName }) }}
|
||||
<template #actions>
|
||||
<Button type="colored" color="blue" size="lg" @click="emit('review', $event)">
|
||||
<DownloadIcon aria-hidden="true" />
|
||||
{{ formatMessage(messages.sharedInstanceReviewUpdateButton) }}
|
||||
</Button>
|
||||
</template>
|
||||
</Admonition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DownloadIcon } from '@modrinth/assets'
|
||||
import { Admonition, Button, useVIntl } from '@modrinth/ui'
|
||||
|
||||
import { instanceAdmonitionsMessages as messages } from './messages'
|
||||
|
||||
defineProps<{
|
||||
instanceName: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
review: [event: MouseEvent]
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
</script>
|
||||
@@ -2,7 +2,6 @@ import type { StackedAdmonitionItem } from '@modrinth/ui'
|
||||
|
||||
export type InstanceAdmonitionKind =
|
||||
| 'shared-instance-stale'
|
||||
| 'shared-instance-update-available'
|
||||
| 'shared-instance-unavailable'
|
||||
| 'shared-instance-wrong-account'
|
||||
|
||||
|
||||
@@ -25,60 +25,39 @@
|
||||
</template>
|
||||
|
||||
<template #metadata>
|
||||
<div v-if="isServerInstance" class="flex flex-wrap items-center gap-2">
|
||||
<InstanceHeaderServerMetadata
|
||||
:loading-server-ping="loadingServerPing"
|
||||
:players-online="playersOnline"
|
||||
:status-online="statusOnline"
|
||||
:recent-plays="recentPlays"
|
||||
:ping="ping"
|
||||
:minecraft-server="minecraftServer"
|
||||
:linked-project-v3="linkedProjectV3"
|
||||
:instance-id="instance.id"
|
||||
/>
|
||||
<PageHeaderMetadataItem v-if="sharedInstanceManager" :action="sharedInstanceManagerAction">
|
||||
{{ sharedInstanceManagerLabel }}
|
||||
<Avatar
|
||||
:src="sharedInstanceManager.avatarUrl"
|
||||
:alt="sharedInstanceManager.name"
|
||||
:tint-by="sharedInstanceManager.tintBy"
|
||||
size="24px"
|
||||
:circle="sharedInstanceManager.type === 'user'"
|
||||
no-shadow
|
||||
/>
|
||||
<span class="min-w-0 truncate">{{ sharedInstanceManager.name }}</span>
|
||||
</PageHeaderMetadataItem>
|
||||
</div>
|
||||
<InstanceHeaderServerMetadata
|
||||
v-if="isServerInstance"
|
||||
:loading-server-ping="loadingServerPing"
|
||||
:players-online="playersOnline"
|
||||
:status-online="statusOnline"
|
||||
:ping="ping"
|
||||
:minecraft-server="minecraftServer"
|
||||
:show-instance-play-time="showInstancePlayTime"
|
||||
:playtime-label="playtimeLabel"
|
||||
/>
|
||||
<PageHeaderMetadata v-else>
|
||||
<PageHeaderMetadataItem :icon="Gamepad2Icon" tooltip="Minecraft version">
|
||||
Minecraft {{ instance.game_version }}
|
||||
</PageHeaderMetadataItem>
|
||||
<PageHeaderMetadataItem
|
||||
v-if="sharedInstanceManager?.type !== 'user'"
|
||||
:icon="TagIcon"
|
||||
:icon-props="{ tag: loaderDisplayName, enforceType: 'loader' }"
|
||||
tooltip="Mod loader"
|
||||
tooltip="Mod loader and Minecraft version"
|
||||
>
|
||||
{{ loaderLabel }}
|
||||
</PageHeaderMetadataItem>
|
||||
<PageHeaderMetadataItem
|
||||
v-if="showInstancePlayTime"
|
||||
v-if="showInstancePlayTime && playtimeLabel"
|
||||
:icon="TimerIcon"
|
||||
tooltip="Total playtime"
|
||||
>
|
||||
{{ playtimeLabel }}
|
||||
</PageHeaderMetadataItem>
|
||||
<PageHeaderMetadataItem v-if="sharedInstanceManager" :action="sharedInstanceManagerAction">
|
||||
{{ sharedInstanceManagerLabel }}
|
||||
<Avatar
|
||||
:src="sharedInstanceManager.avatarUrl"
|
||||
:alt="sharedInstanceManager.name"
|
||||
:tint-by="sharedInstanceManager.tintBy"
|
||||
size="24px"
|
||||
:circle="sharedInstanceManager.type === 'user'"
|
||||
no-shadow
|
||||
/>
|
||||
<span class="min-w-0 truncate">{{ sharedInstanceManager.name }}</span>
|
||||
<PageHeaderMetadataTimeItem
|
||||
v-if="instance.last_played"
|
||||
:icon="ClockIcon"
|
||||
:date="instance.last_played"
|
||||
:label="formatMessage(messages.lastPlayed)"
|
||||
/>
|
||||
<PageHeaderMetadataItem v-else :icon="ClockIcon" tooltip="Last played">
|
||||
{{ formatMessage(messages.neverPlayed) }}
|
||||
</PageHeaderMetadataItem>
|
||||
</PageHeaderMetadata>
|
||||
</template>
|
||||
@@ -185,6 +164,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import {
|
||||
ClockIcon,
|
||||
DownloadIcon,
|
||||
ExternalIcon,
|
||||
FolderOpenIcon,
|
||||
@@ -195,7 +175,6 @@ import {
|
||||
ReportIcon,
|
||||
SettingsIcon,
|
||||
StopCircleIcon,
|
||||
TagCategoryGamepad2Icon as Gamepad2Icon,
|
||||
TimerIcon,
|
||||
UnknownIcon,
|
||||
} from '@modrinth/assets'
|
||||
@@ -211,12 +190,12 @@ import {
|
||||
PageHeaderBadgeItem,
|
||||
PageHeaderMetadata,
|
||||
PageHeaderMetadataItem,
|
||||
PageHeaderMetadataTimeItem,
|
||||
type ServerLoader,
|
||||
TagIcon,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import type { GameInstance } from '@/helpers/types'
|
||||
|
||||
@@ -247,6 +226,10 @@ const messages = defineMessages({
|
||||
id: 'instance.playtime.never-played',
|
||||
defaultMessage: 'Never played',
|
||||
},
|
||||
lastPlayed: {
|
||||
id: 'instance.last-played',
|
||||
defaultMessage: 'Last played',
|
||||
},
|
||||
openFolder: {
|
||||
id: 'instance.action.open-folder',
|
||||
defaultMessage: 'Open folder',
|
||||
@@ -276,7 +259,6 @@ const messages = defineMessages({
|
||||
defaultMessage: "This instance's content is being shared to other users.",
|
||||
},
|
||||
})
|
||||
const router = useRouter()
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -291,16 +273,8 @@ const props = withDefaults(
|
||||
loadingServerPing?: boolean
|
||||
playersOnline?: number
|
||||
statusOnline?: boolean
|
||||
recentPlays?: number
|
||||
ping?: number
|
||||
minecraftServer?: Labrinth.Projects.v3.Project['minecraft_server']
|
||||
linkedProjectV3?: Labrinth.Projects.v3.Project
|
||||
sharedInstanceManager?: {
|
||||
type: 'user' | 'server'
|
||||
name: string
|
||||
avatarUrl?: string
|
||||
tintBy: string
|
||||
} | null
|
||||
}>(),
|
||||
{
|
||||
iconSrc: null,
|
||||
@@ -313,11 +287,8 @@ const props = withDefaults(
|
||||
loadingServerPing: false,
|
||||
playersOnline: undefined,
|
||||
statusOnline: false,
|
||||
recentPlays: undefined,
|
||||
ping: undefined,
|
||||
minecraftServer: undefined,
|
||||
linkedProjectV3: undefined,
|
||||
sharedInstanceManager: null,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -346,7 +317,7 @@ const { formatMessage } = useVIntl()
|
||||
const isInstalling = computed(() => installingStages.includes(props.instance.install_stage))
|
||||
const loaderDisplayName = computed(() => formatLoaderLabel(props.instance.loader) as ServerLoader)
|
||||
const loaderLabel = computed(() =>
|
||||
[loaderDisplayName.value, props.instance.loader_version].filter(Boolean).join(' '),
|
||||
[loaderDisplayName.value, props.instance.game_version].filter(Boolean).join(' '),
|
||||
)
|
||||
const sharedInstanceTooltip = computed(() =>
|
||||
formatMessage(
|
||||
@@ -355,29 +326,23 @@ const sharedInstanceTooltip = computed(() =>
|
||||
: messages.sharedInstanceTooltip,
|
||||
),
|
||||
)
|
||||
const sharedInstanceManagerLabel = computed(() =>
|
||||
props.sharedInstanceManager?.type === 'server' ? 'Linked to' : 'Managed by',
|
||||
)
|
||||
const sharedInstanceManagerAction = computed(() => {
|
||||
const manager = props.sharedInstanceManager
|
||||
if (manager?.type !== 'user') return undefined
|
||||
return () => router.push(`/user/${encodeURIComponent(manager.name)}`)
|
||||
})
|
||||
const playtimeLabel = computed(() => {
|
||||
if (props.timePlayed <= 0) return formatMessage(messages.neverPlayed)
|
||||
const seconds = Math.floor(props.timePlayed)
|
||||
if (seconds <= 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const hours = Math.floor(props.timePlayed / 3600)
|
||||
const hours = Math.floor(seconds / 3600)
|
||||
if (hours >= 1) {
|
||||
return `${hours} hour${hours > 1 ? 's' : ''}`
|
||||
}
|
||||
|
||||
const minutes = Math.floor(props.timePlayed / 60)
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
if (minutes >= 1) {
|
||||
return `${minutes} minute${minutes > 1 ? 's' : ''}`
|
||||
}
|
||||
|
||||
const seconds = Math.floor(props.timePlayed)
|
||||
return `${seconds} second${seconds > 1 ? 's' : ''}`
|
||||
return `${seconds} second${seconds === 1 ? '' : 's'}`
|
||||
})
|
||||
const serverPlayOptions = computed<OverflowMenuOption[]>(() => [
|
||||
{
|
||||
|
||||
+25
-42
@@ -1,52 +1,36 @@
|
||||
<template>
|
||||
<div class="flex items-center flex-wrap gap-2">
|
||||
<template v-if="loadingServerPing">
|
||||
<ServerOnlinePlayers
|
||||
v-if="playersOnline !== undefined"
|
||||
:online="playersOnline"
|
||||
<PageHeaderMetadata>
|
||||
<PageHeaderMetadataItem v-if="loadingServerPing && playersOnline !== undefined">
|
||||
<ServerOnlinePlayers :online="playersOnline" :status-online="statusOnline" hide-label />
|
||||
</PageHeaderMetadataItem>
|
||||
<PageHeaderMetadataItem
|
||||
v-if="minecraftServer?.region || (loadingServerPing && ping !== undefined)"
|
||||
>
|
||||
<ServerRegion v-if="minecraftServer?.region" :region="minecraftServer.region" />
|
||||
<ServerPing
|
||||
v-if="loadingServerPing && ping !== undefined"
|
||||
:ping="ping"
|
||||
: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" />
|
||||
|
||||
<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="instanceId"
|
||||
size="24px"
|
||||
/>
|
||||
<router-link
|
||||
:to="`/project/${linkedProjectV3.slug ?? linkedProjectV3.id}`"
|
||||
class="hover:underline text-primary truncate"
|
||||
>
|
||||
{{ linkedProjectV3.name }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</PageHeaderMetadataItem>
|
||||
<PageHeaderMetadataItem
|
||||
v-if="showInstancePlayTime && playtimeLabel"
|
||||
:icon="TimerIcon"
|
||||
tooltip="Total playtime"
|
||||
>
|
||||
{{ playtimeLabel }}
|
||||
</PageHeaderMetadataItem>
|
||||
</PageHeaderMetadata>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { TimerIcon } from '@modrinth/assets'
|
||||
import {
|
||||
Avatar,
|
||||
PageHeaderMetadata,
|
||||
PageHeaderMetadataItem,
|
||||
ServerOnlinePlayers,
|
||||
ServerPing,
|
||||
ServerRecentPlays,
|
||||
ServerRegion,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
@@ -54,10 +38,9 @@ defineProps<{
|
||||
loadingServerPing?: boolean
|
||||
playersOnline?: number
|
||||
statusOnline?: boolean
|
||||
recentPlays?: number
|
||||
ping?: number
|
||||
minecraftServer?: Labrinth.Projects.v3.Project['minecraft_server']
|
||||
linkedProjectV3?: Labrinth.Projects.v3.Project
|
||||
instanceId?: string
|
||||
showInstancePlayTime?: boolean
|
||||
playtimeLabel?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
+1
@@ -232,6 +232,7 @@ provideInstallationSettings({
|
||||
() =>
|
||||
isModrinthLinkedModpack.value ||
|
||||
isImportedModpack.value ||
|
||||
instance.value.link?.type === 'server_project' ||
|
||||
isSharedInstanceManagedModpack.value,
|
||||
),
|
||||
isBusy: installationSettingsBusy,
|
||||
|
||||
@@ -15,27 +15,28 @@
|
||||
:share-text="formatMessage(messages.shareText)"
|
||||
:open-in-new-tab="false"
|
||||
/>
|
||||
<ModpackContentModal
|
||||
ref="modpackContentModal"
|
||||
:modpack-name="displayedModpackProject?.title"
|
||||
:modpack-icon-url="displayedModpackProject?.icon_url ?? undefined"
|
||||
<ManagedContentModal
|
||||
ref="managedContentModal"
|
||||
:header="managedContentModalHeader"
|
||||
:source-name="managedContent?.card.manager.name"
|
||||
:source-icon-url="managedContent?.card.manager.iconUrl"
|
||||
:enable-toggle="!isServerInstance && !isSharedMember && !isQuarantined"
|
||||
:busy="isBulkOperating"
|
||||
:action-disabled="isBulkOperating || isInstanceBusy"
|
||||
:get-overflow-options="getOverflowOptions"
|
||||
:switch-version="
|
||||
isServerInstance || isSharedMember || isQuarantined ? undefined : handleSwitchVersion
|
||||
"
|
||||
@update:enabled="handleModpackContentToggle"
|
||||
@bulk:enable="(items) => handleModpackContentBulkToggle(items, true)"
|
||||
@bulk:disable="(items) => handleModpackContentBulkToggle(items, false)"
|
||||
@update:enabled="handleManagedContentToggle"
|
||||
@bulk:enable="(items) => handleManagedContentBulkToggle(items, true)"
|
||||
@bulk:disable="(items) => handleManagedContentBulkToggle(items, false)"
|
||||
/>
|
||||
<ConfirmDisableModal
|
||||
ref="sharedDisableConfirmModal"
|
||||
:count="pendingModpackDisableItems.length"
|
||||
:count="pendingManagedContentDisableItems.length"
|
||||
:item-type="formatMessage(messages.contentTypeProject)"
|
||||
:warning="managedContentPolicy.disableWarning(pendingModpackDisableItems)"
|
||||
:warning="managedContentPolicy.disableWarning(pendingManagedContentDisableItems)"
|
||||
:action-disabled="isInstanceBusy"
|
||||
@disable="confirmPendingModpackContentDisable"
|
||||
@disable="confirmPendingManagedContentDisable"
|
||||
/>
|
||||
<ConfirmModpackUpdateModal
|
||||
ref="modpackUpdateConfirmModal"
|
||||
@@ -88,7 +89,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { ClipboardCopyIcon, FolderOpenIcon } from '@modrinth/assets'
|
||||
import { ClipboardCopyIcon, FolderOpenIcon, LockIcon, LockOpenIcon } from '@modrinth/assets'
|
||||
import {
|
||||
type BulkOperationStatus,
|
||||
commonMessages,
|
||||
@@ -96,18 +97,20 @@ import {
|
||||
ConfirmModpackUpdateModal,
|
||||
ContentCardLayout as ContentPageLayout,
|
||||
type ContentItem,
|
||||
type ContentModpackCardCategory,
|
||||
type ContentModpackCardProject,
|
||||
type ContentModpackCardVersion,
|
||||
type ContentOwner,
|
||||
ContentUpdaterModal,
|
||||
dedupeManagedContentItems,
|
||||
defineMessages,
|
||||
injectNotificationManager,
|
||||
ModpackContentModal,
|
||||
type ModpackContentModalState,
|
||||
type ManagedContentData,
|
||||
ManagedContentModal,
|
||||
type ManagedContentModalState,
|
||||
type ManagedContentProject,
|
||||
type ManagedContentVersion,
|
||||
type OverflowMenuOption,
|
||||
provideContentManager,
|
||||
ReadyTransition,
|
||||
summarizeManagedContent,
|
||||
UnknownFileWarningModal,
|
||||
useDebugLogger,
|
||||
useVIntl,
|
||||
@@ -135,8 +138,10 @@ import {
|
||||
add_project_from_path,
|
||||
edit,
|
||||
get_linked_modpack_content,
|
||||
get_shared_instance_publish_preview,
|
||||
is_file_on_modrinth,
|
||||
remove_project,
|
||||
set_project_locked,
|
||||
switch_project_version_with_dependencies,
|
||||
toggle_disable_project,
|
||||
update_all,
|
||||
@@ -152,8 +157,17 @@ import type { FeatureFlag } from '@/store/theme'
|
||||
|
||||
import { injectInstancePage } from '../instance-context'
|
||||
import { instanceContentQueryOptions, instanceKeys } from '../query-options'
|
||||
import { injectSharedInstance } from '../shared-instance-context'
|
||||
|
||||
const messages = defineMessages({
|
||||
modpackContentHeader: {
|
||||
id: 'app.instance.content.managed-content.modpack-header',
|
||||
defaultMessage: 'Modpack content',
|
||||
},
|
||||
sharedContentHeader: {
|
||||
id: 'app.instance.content.managed-content.shared-header',
|
||||
defaultMessage: 'Shared content',
|
||||
},
|
||||
shareTitle: {
|
||||
id: 'app.instance.mods.share-title',
|
||||
defaultMessage: 'Sharing modpack content',
|
||||
@@ -178,6 +192,14 @@ const messages = defineMessages({
|
||||
id: 'app.instance.mods.locked-content',
|
||||
defaultMessage: 'Content in locked instances cannot be changed.',
|
||||
},
|
||||
freezeContent: {
|
||||
id: 'app.instance.mods.freeze-content',
|
||||
defaultMessage: 'Freeze version',
|
||||
},
|
||||
unfreezeContent: {
|
||||
id: 'app.instance.mods.unfreeze-content',
|
||||
defaultMessage: 'Unfreeze version',
|
||||
},
|
||||
contentTypeProject: {
|
||||
id: 'app.instance.mods.content-type-project',
|
||||
defaultMessage: 'project',
|
||||
@@ -196,7 +218,7 @@ const messages = defineMessages({
|
||||
},
|
||||
})
|
||||
|
||||
let savedModalState: ModpackContentModalState | null = null
|
||||
let savedModalState: ManagedContentModalState | null = null
|
||||
|
||||
function contentOwnerLink(owner: ContentOwner): NonNullable<ContentOwner['link']> {
|
||||
if (owner.type === 'user') return `/user/${encodeURIComponent(owner.id)}`
|
||||
@@ -219,6 +241,7 @@ const skipNonEssentialWarnings = computed(() =>
|
||||
)
|
||||
|
||||
const instancePage = injectInstancePage()
|
||||
const sharedInstanceState = injectSharedInstance()
|
||||
const instance = instancePage.instance
|
||||
const isServerInstance = instancePage.isServerInstance
|
||||
const openSettings = () => instancePage.openSettings(1)
|
||||
@@ -283,15 +306,12 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
const linkedModpackProject = ref<ContentModpackCardProject | null>(null)
|
||||
const linkedModpackVersion = ref<ContentModpackCardVersion | null>(null)
|
||||
const linkedModpackOwner = ref<ContentOwner | null>(null)
|
||||
const linkedModpackCategories = ref<ContentModpackCardCategory[]>([])
|
||||
const linkedModpackHasUpdate = ref(false)
|
||||
const linkedModpackProject = ref<ManagedContentProject | null>(null)
|
||||
const linkedModpackVersion = ref<ManagedContentVersion | null>(null)
|
||||
const linkedModpackUpdateVersionId = ref<string | null>(null)
|
||||
const localImportedModpackUnlinked = ref(false)
|
||||
|
||||
const localImportedModpackProject = computed<ContentModpackCardProject | null>(() => {
|
||||
const localImportedModpackProject = computed<ManagedContentProject | null>(() => {
|
||||
const link = instance.value.link
|
||||
if (localImportedModpackUnlinked.value || link?.type !== 'imported_modpack') return null
|
||||
|
||||
@@ -300,7 +320,6 @@ const localImportedModpackProject = computed<ContentModpackCardProject | null>((
|
||||
slug: link.filename ?? instance.value.id,
|
||||
title: link.name ?? instance.value.name,
|
||||
icon_url: instance.value.icon_path ? convertFileSrc(instance.value.icon_path) : undefined,
|
||||
description: '',
|
||||
filename: link.filename ?? undefined,
|
||||
}
|
||||
})
|
||||
@@ -319,6 +338,7 @@ watch(
|
||||
const isModpackUpdating = ref(false)
|
||||
const isBulkOperating = ref(false)
|
||||
const isInstanceBusy = computed(() => instance.value?.install_stage !== 'installed')
|
||||
const showSharedContentFilter = computed(() => instance.value.shared_instance?.role === 'member')
|
||||
const isPackLocked = computed(
|
||||
() =>
|
||||
instance.value.quarantined ||
|
||||
@@ -329,10 +349,10 @@ const isPackLocked = computed(
|
||||
const shareModal = ref<InstanceType<typeof ShareModalWrapper> | null>()
|
||||
const exportModal = ref(null)
|
||||
const contentUpdaterModal = ref<InstanceType<typeof ContentUpdaterModal> | null>()
|
||||
const modpackContentModal = ref<InstanceType<typeof ModpackContentModal> | null>()
|
||||
const managedContentModal = ref<InstanceType<typeof ManagedContentModal> | null>()
|
||||
const modpackUpdateConfirmModal = ref<InstanceType<typeof ConfirmModpackUpdateModal> | null>()
|
||||
const sharedDisableConfirmModal = ref<InstanceType<typeof ConfirmDisableModal> | null>()
|
||||
const pendingModpackDisableItems = ref<ContentItem[]>([])
|
||||
const pendingManagedContentDisableItems = ref<ContentItem[]>([])
|
||||
const unknownFileWarningModal = ref<InstanceType<typeof UnknownFileWarningModal> | null>()
|
||||
const unknownFileName = ref('')
|
||||
let resolveUnknownFileConfirmation: ((confirmed: boolean) => void) | null = null
|
||||
@@ -349,6 +369,134 @@ const modpackContentQuery = useQuery({
|
||||
),
|
||||
})
|
||||
|
||||
const hasSharedManagedContent = computed(() => {
|
||||
if (instance.value.shared_instance?.role === 'owner') return false
|
||||
|
||||
const linkType = instance.value.link?.type
|
||||
return (
|
||||
!!instance.value.shared_instance ||
|
||||
linkType === 'server_project' ||
|
||||
linkType === 'server_project_modpack'
|
||||
)
|
||||
})
|
||||
|
||||
const managedContentItems = computed(() => {
|
||||
const linkedContent = modpackContentQuery.data.value ?? []
|
||||
const sourcedContent = hasSharedManagedContent.value
|
||||
? projects.value.filter((item) =>
|
||||
['server_project', 'shared_instance'].includes(item.source_kind ?? ''),
|
||||
)
|
||||
: []
|
||||
|
||||
return dedupeManagedContentItems([...linkedContent, ...sourcedContent])
|
||||
})
|
||||
|
||||
const managedContentSummary = computed(() =>
|
||||
modpackContentQuery.isLoading.value && modpackContentQuery.data.value === undefined
|
||||
? undefined
|
||||
: summarizeManagedContent(managedContentItems.value),
|
||||
)
|
||||
|
||||
const managedContent = computed<ManagedContentData | null>(() => {
|
||||
const attachment = instance.value.shared_instance
|
||||
const sharedManager = sharedInstanceState.manager.value
|
||||
const linkedProject = instancePage.linkedProject.value
|
||||
const linkType = instance.value.link?.type
|
||||
const isSharedOwner = attachment?.role === 'owner'
|
||||
|
||||
if (
|
||||
!isSharedOwner &&
|
||||
(attachment || linkType === 'server_project' || linkType === 'server_project_modpack')
|
||||
) {
|
||||
const serverManaged =
|
||||
sharedManager?.type === 'server' ||
|
||||
!!attachment?.server_manager_name ||
|
||||
linkType === 'server_project' ||
|
||||
linkType === 'server_project_modpack' ||
|
||||
(!attachment && isServerInstance.value)
|
||||
const managerName = serverManaged
|
||||
? (sharedManager?.name ??
|
||||
attachment?.server_manager_name ??
|
||||
linkedProject?.name ??
|
||||
instance.value.name)
|
||||
: (sharedManager?.name ?? instance.value.name)
|
||||
const managerIcon = serverManaged
|
||||
? (sharedManager?.avatarUrl ??
|
||||
attachment?.server_manager_icon_url ??
|
||||
linkedProject?.icon_url ??
|
||||
undefined)
|
||||
: (sharedManager?.avatarUrl ??
|
||||
(instance.value.icon_path ? convertFileSrc(instance.value.icon_path) : undefined))
|
||||
const managerLink = serverManaged
|
||||
? linkedProject
|
||||
? {
|
||||
path: `/project/${linkedProject.slug ?? linkedProject.id}`,
|
||||
query: { i: instancePage.instanceId.value },
|
||||
}
|
||||
: undefined
|
||||
: sharedManager?.type === 'user'
|
||||
? `/user/${encodeURIComponent(sharedManager.name)}`
|
||||
: undefined
|
||||
|
||||
return {
|
||||
card: {
|
||||
kind: serverManaged ? 'server' : 'shared-instance',
|
||||
installing: isInstanceBusy.value,
|
||||
manager: {
|
||||
name: managerName,
|
||||
iconUrl: managerIcon,
|
||||
link: managerLink,
|
||||
},
|
||||
summary: managedContentSummary.value,
|
||||
syncedAt: sharedInstanceState.lastUpdateCheckAt.value,
|
||||
updateAvailable: instancePage.sharedInstanceUpdateAvailable.value,
|
||||
},
|
||||
disabled: attachment?.status === 'applying' || isInstanceBusy.value,
|
||||
disabledText: formatMessage(commonMessages.updatingLabel),
|
||||
}
|
||||
}
|
||||
|
||||
const project = displayedModpackProject.value
|
||||
if (!project) return null
|
||||
|
||||
return {
|
||||
card: {
|
||||
kind: 'modpack',
|
||||
installing: isInstanceBusy.value,
|
||||
manager: {
|
||||
name: project.title,
|
||||
iconUrl: project.icon_url ?? undefined,
|
||||
link: linkedModpackProject.value
|
||||
? {
|
||||
path: `/project/${project.slug ?? project.id}`,
|
||||
query: { i: instancePage.instanceId.value },
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
summary: managedContentSummary.value,
|
||||
versionNumber: linkedModpackVersion.value?.version_number,
|
||||
versionLink:
|
||||
linkedModpackProject.value && linkedModpackVersion.value
|
||||
? {
|
||||
path: `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}/version/${linkedModpackVersion.value.id}`,
|
||||
query: { i: instancePage.instanceId.value },
|
||||
}
|
||||
: undefined,
|
||||
updatedAt: linkedModpackVersion.value?.date_published,
|
||||
},
|
||||
disabled: isModpackUpdating.value || isInstanceBusy.value,
|
||||
disabledText: formatMessage(commonMessages.updatingLabel),
|
||||
}
|
||||
})
|
||||
|
||||
const managedContentModalHeader = computed(() =>
|
||||
formatMessage(
|
||||
managedContent.value?.card.kind === 'modpack'
|
||||
? messages.modpackContentHeader
|
||||
: messages.sharedContentHeader,
|
||||
),
|
||||
)
|
||||
|
||||
// TODO: Extract content operation and updater modal state into composables; this page currently owns file mutations, dependency installs, busy flags, and version selection flow.
|
||||
const updatingProject = ref<ContentItem | null>(null)
|
||||
const updatingProjectVersions = ref<Labrinth.Versions.v2.Version[]>([])
|
||||
@@ -418,14 +566,30 @@ function canDeleteContent(item: ContentItem) {
|
||||
return canMutateContent(item)
|
||||
}
|
||||
|
||||
function canToggleContent(item: ContentItem) {
|
||||
return canMutateContent(item)
|
||||
}
|
||||
|
||||
function canChangeContentVersion(item: ContentItem) {
|
||||
return canMutateContent(item) && !item.locked
|
||||
}
|
||||
|
||||
async function reconcileSharedInstancePublishState() {
|
||||
if (instance.value.shared_instance?.role !== 'owner') return
|
||||
|
||||
await get_shared_instance_publish_preview(instance.value.id).catch((error) => {
|
||||
debug('Failed to reconcile shared instance publish state', { error })
|
||||
})
|
||||
}
|
||||
|
||||
function setContentItemBusy(item: ContentItem, busy: boolean, originalFileName = item.file_name) {
|
||||
item.installing = busy
|
||||
modpackContentModal.value?.updateItem(originalFileName, {
|
||||
managedContentModal.value?.updateItem(originalFileName, {
|
||||
installing: busy,
|
||||
disabled: busy,
|
||||
})
|
||||
if (item.file_name !== originalFileName) {
|
||||
modpackContentModal.value?.updateItem(item.file_name, {
|
||||
managedContentModal.value?.updateItem(item.file_name, {
|
||||
installing: busy,
|
||||
disabled: busy,
|
||||
})
|
||||
@@ -627,8 +791,12 @@ async function handleUnknownFileContinue(dontShowAgain: boolean) {
|
||||
resolveUnknownFileWarning(true)
|
||||
}
|
||||
|
||||
async function toggleDisableMod(mod: ContentItem, desiredEnabled?: boolean) {
|
||||
if (!mod.file_path) return
|
||||
async function toggleDisableMod(
|
||||
mod: ContentItem,
|
||||
desiredEnabled?: boolean,
|
||||
reconcileSharedState = true,
|
||||
) {
|
||||
if (!mod.file_path || !canToggleContent(mod)) return
|
||||
const operation = beginContentOperation(mod)
|
||||
if (!operation) return
|
||||
const originalFilePath = mod.file_path
|
||||
@@ -640,7 +808,7 @@ async function toggleDisableMod(mod: ContentItem, desiredEnabled?: boolean) {
|
||||
mod.file_path = newPath
|
||||
mod.file_name = newFileName
|
||||
mod.enabled = enabled
|
||||
modpackContentModal.value?.updateItem(operation.originalFileName, {
|
||||
managedContentModal.value?.updateItem(operation.originalFileName, {
|
||||
file_path: newPath,
|
||||
file_name: newFileName,
|
||||
enabled,
|
||||
@@ -659,6 +827,10 @@ async function toggleDisableMod(mod: ContentItem, desiredEnabled?: boolean) {
|
||||
project_type: mod.project_type,
|
||||
disabled: !enabled,
|
||||
})
|
||||
|
||||
if (reconcileSharedState) {
|
||||
await reconcileSharedInstancePublishState()
|
||||
}
|
||||
} catch (err) {
|
||||
handleError(err as Error)
|
||||
} finally {
|
||||
@@ -669,7 +841,7 @@ async function toggleDisableMod(mod: ContentItem, desiredEnabled?: boolean) {
|
||||
const toggleDisableDebounced = toggleDisableMod
|
||||
|
||||
async function removeMod(mod: ContentItem) {
|
||||
if (!mod.file_path) return
|
||||
if (!mod.file_path || !canDeleteContent(mod)) return
|
||||
const operation = beginContentOperation(mod)
|
||||
if (!operation) return
|
||||
|
||||
@@ -800,7 +972,7 @@ async function bulkUpdateAllProjects(onProgress?: (status: BulkOperationStatus)
|
||||
}
|
||||
|
||||
async function updateProject(mod: ContentItem) {
|
||||
if (!canUpdateProject(mod)) return
|
||||
if (!canUpdateProject(mod) || mod.locked) return
|
||||
const operation = beginContentOperation(mod)
|
||||
if (!operation) return
|
||||
|
||||
@@ -829,7 +1001,7 @@ async function updateProject(mod: ContentItem) {
|
||||
}
|
||||
|
||||
async function switchProjectVersion(mod: ContentItem, version: Labrinth.Versions.v2.Version) {
|
||||
if (!canMutateContent(mod)) return
|
||||
if (!canChangeContentVersion(mod)) return
|
||||
if (!mod.file_path) return
|
||||
const operation = beginContentOperation(mod)
|
||||
if (!operation) return
|
||||
@@ -856,7 +1028,8 @@ async function switchProjectVersion(mod: ContentItem, version: Labrinth.Versions
|
||||
|
||||
async function handleUpdate(id: string) {
|
||||
const item = projects.value.find((p) => getContentItemId(p) === id)
|
||||
if (!item || !canUpdateProject(item) || !item.project?.id || !item.version?.id) return
|
||||
if (!item || item.locked || !canUpdateProject(item) || !item.project?.id || !item.version?.id)
|
||||
return
|
||||
|
||||
const requestId = beginUpdateRequest()
|
||||
const itemId = getContentItemId(item)
|
||||
@@ -966,7 +1139,7 @@ async function handleUpdate(id: string) {
|
||||
}
|
||||
|
||||
async function handleSwitchVersion(item: ContentItem) {
|
||||
if (!canMutateContent(item)) return
|
||||
if (!canChangeContentVersion(item)) return
|
||||
if (!item.project?.id || !item.version?.id) return
|
||||
|
||||
const requestId = beginUpdateRequest()
|
||||
@@ -993,9 +1166,9 @@ async function handleSwitchVersion(item: ContentItem) {
|
||||
updatingProjectVersions.value = versions
|
||||
}
|
||||
|
||||
async function handleModpackContentToggle(item: ContentItem, enabled: boolean) {
|
||||
async function handleManagedContentToggle(item: ContentItem, enabled: boolean) {
|
||||
if (!enabled && managedContentPolicy.disableWarning([item])) {
|
||||
pendingModpackDisableItems.value = [item]
|
||||
pendingManagedContentDisableItems.value = [item]
|
||||
sharedDisableConfirmModal.value?.show()
|
||||
return
|
||||
}
|
||||
@@ -1003,47 +1176,48 @@ async function handleModpackContentToggle(item: ContentItem, enabled: boolean) {
|
||||
await toggleDisableDebounced(item, enabled)
|
||||
}
|
||||
|
||||
async function handleModpackContentBulkToggle(items: ContentItem[], enabled: boolean) {
|
||||
async function handleManagedContentBulkToggle(items: ContentItem[], enabled: boolean) {
|
||||
if (!enabled && managedContentPolicy.disableWarning(items)) {
|
||||
pendingModpackDisableItems.value = items
|
||||
pendingManagedContentDisableItems.value = items
|
||||
sharedDisableConfirmModal.value?.show()
|
||||
return
|
||||
}
|
||||
|
||||
await setModpackContentEnabled(items, enabled)
|
||||
await setManagedContentEnabled(items, enabled)
|
||||
}
|
||||
|
||||
async function confirmPendingModpackContentDisable() {
|
||||
const items = [...pendingModpackDisableItems.value]
|
||||
pendingModpackDisableItems.value = []
|
||||
await setModpackContentEnabled(items, false)
|
||||
async function confirmPendingManagedContentDisable() {
|
||||
const items = [...pendingManagedContentDisableItems.value]
|
||||
pendingManagedContentDisableItems.value = []
|
||||
await setManagedContentEnabled(items, false)
|
||||
}
|
||||
|
||||
async function setModpackContentEnabled(items: ContentItem[], enabled: boolean) {
|
||||
await Promise.all(items.map((item) => toggleDisableMod(item, enabled)))
|
||||
async function setManagedContentEnabled(items: ContentItem[], enabled: boolean) {
|
||||
await Promise.all(items.map((item) => toggleDisableMod(item, enabled, false)))
|
||||
await reconcileSharedInstancePublishState()
|
||||
}
|
||||
|
||||
async function handleModpackContent() {
|
||||
async function handleManagedContent() {
|
||||
if (!instance.value?.id) return
|
||||
|
||||
if (modpackContentQuery.data.value?.length) {
|
||||
modpackContentModal.value?.show(modpackContentQuery.data.value)
|
||||
if (modpackContentQuery.data.value !== undefined) {
|
||||
managedContentModal.value?.show(managedContentItems.value)
|
||||
return
|
||||
}
|
||||
|
||||
modpackContentModal.value?.showLoading()
|
||||
managedContentModal.value?.showLoading()
|
||||
|
||||
const { data, error } = await modpackContentQuery.refetch()
|
||||
|
||||
if (data !== undefined) {
|
||||
modpackContentModal.value?.show(data)
|
||||
managedContentModal.value?.show(managedContentItems.value)
|
||||
} else {
|
||||
if (error) handleError(error)
|
||||
modpackContentModal.value?.hide()
|
||||
managedContentModal.value?.hide()
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshModpackContentItems(cacheBehaviour?: CacheBehaviour) {
|
||||
async function refreshManagedContentItems(cacheBehaviour?: CacheBehaviour) {
|
||||
if (!instance.value?.id) return
|
||||
|
||||
const contentItems = await queryClient
|
||||
@@ -1054,13 +1228,13 @@ async function refreshModpackContentItems(cacheBehaviour?: CacheBehaviour) {
|
||||
.catch(handleError)
|
||||
|
||||
if (contentItems) {
|
||||
modpackContentModal.value?.setItems(contentItems)
|
||||
managedContentModal.value?.setItems(managedContentItems.value)
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshContentState(cacheBehaviour?: CacheBehaviour) {
|
||||
await initProjects(cacheBehaviour)
|
||||
await refreshModpackContentItems(cacheBehaviour)
|
||||
await refreshManagedContentItems(cacheBehaviour)
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -1093,7 +1267,6 @@ async function handleModpackUpdate() {
|
||||
linkedModpackUpdateVersionId: linkedModpackUpdateVersionId.value,
|
||||
linkedModpackProject: linkedModpackProject.value,
|
||||
linkedModpackVersion: linkedModpackVersion.value,
|
||||
linkedModpackHasUpdate: linkedModpackHasUpdate.value,
|
||||
instance: {
|
||||
path: instance.value.id,
|
||||
name: instance.value.name,
|
||||
@@ -1262,8 +1435,6 @@ async function unpairInstance() {
|
||||
})
|
||||
linkedModpackProject.value = null
|
||||
linkedModpackVersion.value = null
|
||||
linkedModpackOwner.value = null
|
||||
linkedModpackHasUpdate.value = false
|
||||
linkedModpackUpdateVersionId.value = null
|
||||
localImportedModpackUnlinked.value = true
|
||||
await initProjects()
|
||||
@@ -1326,9 +1497,41 @@ function getOverflowOptions(item: ContentItem): OverflowMenuOption[] {
|
||||
})
|
||||
}
|
||||
|
||||
if (canMutateContent(item)) {
|
||||
options.push(
|
||||
{ type: 'divider' },
|
||||
{
|
||||
id: item.locked ? 'unfreeze-content' : 'freeze-content',
|
||||
label: formatMessage(item.locked ? messages.unfreezeContent : messages.freezeContent),
|
||||
icon: item.locked ? LockOpenIcon : LockIcon,
|
||||
action: () => handleContentFreeze(item, !item.locked),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
async function handleContentFreeze(item: ContentItem, frozen: boolean) {
|
||||
if (!item.file_path || !canMutateContent(item)) return
|
||||
const operation = beginContentOperation(item)
|
||||
if (!operation) return
|
||||
const originalFilePath = item.file_path
|
||||
|
||||
try {
|
||||
await set_project_locked(instance.value.id, item.file_path, frozen)
|
||||
item.locked = frozen
|
||||
managedContentModal.value?.updateItem(operation.originalFileName, { locked: frozen })
|
||||
updateLinkedModpackContentCache(item, operation.originalFileName, originalFilePath, {
|
||||
locked: frozen,
|
||||
})
|
||||
} catch (err) {
|
||||
handleError(err as Error)
|
||||
} finally {
|
||||
finishContentOperation(item, operation)
|
||||
}
|
||||
}
|
||||
|
||||
async function initProjects(cacheBehaviour?: CacheBehaviour, staleTime = 0) {
|
||||
if (!instance.value) return
|
||||
|
||||
@@ -1358,16 +1561,10 @@ function applyContentData(contentData: InstanceContentData) {
|
||||
if (contentData.modpack) {
|
||||
linkedModpackProject.value = contentData.modpack.project
|
||||
linkedModpackVersion.value = contentData.modpack.version
|
||||
linkedModpackOwner.value = contentData.modpack.owner
|
||||
linkedModpackCategories.value = contentData.modpack.categories
|
||||
linkedModpackHasUpdate.value = contentData.modpack.hasUpdate
|
||||
linkedModpackUpdateVersionId.value = contentData.modpack.updateVersionId
|
||||
} else {
|
||||
linkedModpackProject.value = null
|
||||
linkedModpackVersion.value = null
|
||||
linkedModpackOwner.value = null
|
||||
linkedModpackCategories.value = []
|
||||
linkedModpackHasUpdate.value = false
|
||||
linkedModpackUpdateVersionId.value = null
|
||||
}
|
||||
|
||||
@@ -1375,55 +1572,16 @@ function applyContentData(contentData: InstanceContentData) {
|
||||
return true
|
||||
}
|
||||
|
||||
function contentVersionLabel(item: ContentItem): string {
|
||||
if (item.embedded_metadata?.version) return item.embedded_metadata.version
|
||||
return formatMessage(commonMessages.unknownLabel)
|
||||
}
|
||||
|
||||
provideContentManager({
|
||||
items: mergedProjects,
|
||||
loading,
|
||||
error: ref(null),
|
||||
modpack: computed(() => {
|
||||
if (linkedModpackProject.value) {
|
||||
return {
|
||||
project: linkedModpackProject.value,
|
||||
projectLink: {
|
||||
path: `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}`,
|
||||
query: { i: instancePage.instanceId.value },
|
||||
},
|
||||
version: linkedModpackVersion.value ?? undefined,
|
||||
versionLink:
|
||||
linkedModpackProject.value && linkedModpackVersion.value
|
||||
? {
|
||||
path: `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}/version/${linkedModpackVersion.value.id}`,
|
||||
query: { i: instancePage.instanceId.value },
|
||||
}
|
||||
: undefined,
|
||||
owner: linkedModpackOwner.value
|
||||
? {
|
||||
...linkedModpackOwner.value,
|
||||
link: contentOwnerLink(linkedModpackOwner.value),
|
||||
}
|
||||
: undefined,
|
||||
categories: linkedModpackCategories.value,
|
||||
hasUpdate: linkedModpackHasUpdate.value,
|
||||
disabled: isModpackUpdating.value,
|
||||
disabledText: isModpackUpdating.value
|
||||
? formatMessage(commonMessages.updatingLabel)
|
||||
: formatMessage(commonMessages.installingLabel),
|
||||
}
|
||||
}
|
||||
|
||||
if (localImportedModpackProject.value) {
|
||||
return {
|
||||
project: localImportedModpackProject.value,
|
||||
categories: [],
|
||||
hasUpdate: false,
|
||||
disabled: isModpackUpdating.value,
|
||||
disabledText: isModpackUpdating.value
|
||||
? formatMessage(commonMessages.updatingLabel)
|
||||
: formatMessage(commonMessages.installingLabel),
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}),
|
||||
managedContent,
|
||||
isPackLocked,
|
||||
isBusy: isInstanceBusy,
|
||||
disableAddContent: isQuarantined,
|
||||
@@ -1432,23 +1590,27 @@ provideContentManager({
|
||||
skipNonEssentialWarnings,
|
||||
contentTypeLabel: ref(formatMessage(messages.contentTypeProject)),
|
||||
toggleEnabled: toggleDisableDebounced,
|
||||
bulkEnableItems: (items: ContentItem[]) =>
|
||||
Promise.all(
|
||||
bulkEnableItems: async (items: ContentItem[]) => {
|
||||
await Promise.all(
|
||||
items
|
||||
.filter((item) => canMutateContent(item) && !item.enabled)
|
||||
.map((item) => toggleDisableMod(item, true)),
|
||||
).then(() => {}),
|
||||
bulkDisableItems: (items: ContentItem[]) =>
|
||||
Promise.all(
|
||||
.filter((item) => canToggleContent(item) && !item.enabled)
|
||||
.map((item) => toggleDisableMod(item, true, false)),
|
||||
)
|
||||
await reconcileSharedInstancePublishState()
|
||||
},
|
||||
bulkDisableItems: async (items: ContentItem[]) => {
|
||||
await Promise.all(
|
||||
items
|
||||
.filter((item) => canMutateContent(item) && item.enabled)
|
||||
.map((item) => toggleDisableMod(item, false)),
|
||||
).then(() => {}),
|
||||
.filter((item) => canToggleContent(item) && item.enabled)
|
||||
.map((item) => toggleDisableMod(item, false, false)),
|
||||
)
|
||||
await reconcileSharedInstancePublishState()
|
||||
},
|
||||
deleteItem: removeMod,
|
||||
bulkDeleteItems: (items: ContentItem[]) =>
|
||||
Promise.all(items.filter(canMutateContent).map((item) => removeMod(item))).then(() => {}),
|
||||
Promise.all(items.filter(canDeleteContent).map((item) => removeMod(item))).then(() => {}),
|
||||
canDeleteItem: canDeleteContent,
|
||||
canToggleItem: canMutateContent,
|
||||
canToggleItem: canToggleContent,
|
||||
getDeleteWarning: managedContentPolicy.deleteWarning,
|
||||
getDisableWarning: managedContentPolicy.disableWarning,
|
||||
getDeleteDependencyWarning,
|
||||
@@ -1459,13 +1621,15 @@ provideContentManager({
|
||||
updateItem: handleUpdate,
|
||||
bulkUpdateAll: bulkUpdateAllProjects,
|
||||
bulkUpdateItem: updateProject,
|
||||
updateModpack:
|
||||
isServerInstance.value || isSharedMember.value || isQuarantined.value
|
||||
? undefined
|
||||
: handleModpackUpdate,
|
||||
viewModpackContent: handleModpackContent,
|
||||
runManagedContentPrimaryAction:
|
||||
instance.value.shared_instance?.role === 'member'
|
||||
? instancePage.reviewSharedInstanceUpdate
|
||||
: instance.value.link?.type === 'modrinth_modpack' && !isQuarantined.value
|
||||
? handleModpackUpdate
|
||||
: undefined,
|
||||
viewManagedContent: handleManagedContent,
|
||||
unlinkModpack: unpairInstance,
|
||||
openSettings: openSettings,
|
||||
openManagedContentSettings: openSettings,
|
||||
switchVersion: handleSwitchVersion,
|
||||
getOverflowOptions,
|
||||
shareItems: handleShareItems,
|
||||
@@ -1475,15 +1639,15 @@ provideContentManager({
|
||||
project: item.project ?? {
|
||||
id: item.file_name,
|
||||
slug: null,
|
||||
title: item.file_name.replace('.disabled', ''),
|
||||
icon_url: null,
|
||||
title: item.embedded_metadata?.name ?? item.file_name.replace('.disabled', ''),
|
||||
icon_url: item.embedded_metadata?.icon_url ?? null,
|
||||
},
|
||||
projectLink: item.project?.id
|
||||
? { path: `/project/${item.project.id}`, query: { i: instancePage.instanceId.value } }
|
||||
: undefined,
|
||||
version: item.version ?? {
|
||||
id: item.file_name,
|
||||
version_number: formatMessage(commonMessages.unknownLabel),
|
||||
version_number: contentVersionLabel(item),
|
||||
file_name: item.file_name,
|
||||
},
|
||||
versionLink:
|
||||
@@ -1499,19 +1663,22 @@ provideContentManager({
|
||||
link: contentOwnerLink(item.owner),
|
||||
}
|
||||
: undefined,
|
||||
external: item.external ?? !item.project,
|
||||
enabled: canMutateContent(item) ? item.enabled : undefined,
|
||||
locked: item.locked,
|
||||
installing: item.installing,
|
||||
hideDelete: !canDeleteContent(item),
|
||||
hideSwitchVersion: !canMutateContent(item) || !item.project?.id || !item.version?.id,
|
||||
hasUpdate: canUpdateProject(item),
|
||||
hideSwitchVersion: !canChangeContentVersion(item) || !item.project?.id || !item.version?.id,
|
||||
hasUpdate: canUpdateProject(item) && !item.locked,
|
||||
}),
|
||||
showSharedContentFilter,
|
||||
filterPersistKey: instance.value.id,
|
||||
})
|
||||
|
||||
type UnlistenFn = () => void
|
||||
|
||||
const initialContentReady = loadInitialContent()
|
||||
void initialContentReady.then(restoreModpackContentModalState).catch(handleError)
|
||||
void initialContentReady.then(restoreManagedContentModalState).catch(handleError)
|
||||
|
||||
function getInstallRevision() {
|
||||
return installRevisionByInstance.value.get(instance.value.id) ?? 0
|
||||
@@ -1541,18 +1708,18 @@ watch(contentQuery.error, (error) => {
|
||||
}
|
||||
})
|
||||
|
||||
async function restoreModpackContentModalState() {
|
||||
async function restoreManagedContentModalState() {
|
||||
if (!savedModalState) return
|
||||
|
||||
const stateToRestore = savedModalState
|
||||
savedModalState = null
|
||||
await nextTick()
|
||||
modpackContentModal.value?.restore(stateToRestore)
|
||||
managedContentModal.value?.restore(stateToRestore)
|
||||
}
|
||||
|
||||
// Save modal state when navigating away so it can be restored on back
|
||||
const removeBeforeEach = router.beforeEach(() => {
|
||||
const state = modpackContentModal.value?.getState()
|
||||
const state = managedContentModal.value?.getState()
|
||||
savedModalState = state ?? null
|
||||
})
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface InstancePageContext {
|
||||
readonly instance: ComputedRef<GameInstance>
|
||||
readonly linkedProject: ComputedRef<Labrinth.Projects.v3.Project | undefined>
|
||||
readonly isServerInstance: ComputedRef<boolean>
|
||||
readonly sharedInstanceUpdateAvailable: ComputedRef<boolean>
|
||||
readonly offline: Readonly<Ref<boolean>>
|
||||
readonly playing: ComputedRef<boolean>
|
||||
readonly loading: Readonly<Ref<boolean>>
|
||||
@@ -21,6 +22,7 @@ export interface InstancePageContext {
|
||||
openSettings: (tab?: number) => void
|
||||
browseContent: (projectType?: string) => Promise<void>
|
||||
browseServers: () => Promise<void>
|
||||
reviewSharedInstanceUpdate: (event?: MouseEvent) => void
|
||||
}
|
||||
|
||||
export const [injectInstancePage, provideInstancePage] =
|
||||
|
||||
@@ -37,11 +37,8 @@
|
||||
:loading-server-ping="loadingServerPing"
|
||||
:players-online="playersOnline"
|
||||
:status-online="statusOnline"
|
||||
:recent-plays="recentPlays"
|
||||
:ping="ping"
|
||||
:minecraft-server="minecraftServer"
|
||||
:linked-project-v3="linkedProjectV3"
|
||||
:shared-instance-manager="sharedInstanceManager"
|
||||
@repair="() => repairInstance()"
|
||||
@stop="() => stopInstance('InstancePage')"
|
||||
@play="() => startInstance('InstancePage')"
|
||||
@@ -64,10 +61,8 @@
|
||||
:shared-instance-expected-user-id="sharedInstanceExpectedUserId"
|
||||
:shared-instance-role="instance.shared_instance?.role"
|
||||
:shared-instance-signed-out="sharedInstanceSignedOut"
|
||||
:shared-instance-update-available="showSharedInstanceUpdateAdmonition"
|
||||
@published="refreshInstance"
|
||||
@delete="requestInstanceDeletion"
|
||||
@review-update="reviewSharedInstanceUpdate"
|
||||
/>
|
||||
</div>
|
||||
<div :class="['p-6 pt-4', { 'min-h-0 flex-1 overflow-y-auto': isFixedRender }]">
|
||||
@@ -211,7 +206,9 @@ useQuery(
|
||||
retry: false,
|
||||
})),
|
||||
)
|
||||
const linkedProjectId = computed(() => instance.value?.link?.project_id ?? '')
|
||||
const linkedProjectId = computed(
|
||||
() => instance.value?.link?.server_project_id ?? instance.value?.link?.project_id ?? '',
|
||||
)
|
||||
const linkedProjectQuery = useQuery(
|
||||
computed(() => ({
|
||||
...instanceLinkedProjectQueryOptions(linkedProjectId.value),
|
||||
@@ -302,9 +299,6 @@ const minecraftServer = computed(() => linkedProjectV3.value?.minecraft_server)
|
||||
const javaServerPingData = computed(() => linkedProjectV3.value?.minecraft_java_server?.ping?.data)
|
||||
const liveServerStatusOnline = ref(false)
|
||||
const statusOnline = computed(() => liveServerStatusOnline.value || !!javaServerPingData.value)
|
||||
const recentPlays = computed(
|
||||
() => linkedProjectV3.value?.minecraft_java_server?.verified_plays_2w ?? undefined,
|
||||
)
|
||||
const playersOnline = ref<number | undefined>(undefined)
|
||||
const ping = ref<number | undefined>(undefined)
|
||||
const loadingServerPing = ref(false)
|
||||
@@ -317,7 +311,6 @@ provideSharedInstance(sharedInstanceState)
|
||||
const {
|
||||
actionsLocked: sharedInstanceActionsLocked,
|
||||
expectedUserId: sharedInstanceExpectedUserId,
|
||||
manager: sharedInstanceManager,
|
||||
refreshUpdatePreview: refreshSharedInstanceUpdatePreview,
|
||||
setUnavailable: setSharedInstanceUnavailable,
|
||||
signedOut: sharedInstanceSignedOut,
|
||||
@@ -331,7 +324,7 @@ const sharedInstanceUpdateKey = computed(() => {
|
||||
const latestVersion = sharedInstanceUpdatePreview.value?.latestVersion
|
||||
return instanceId && latestVersion !== undefined ? `${instanceId}:${latestVersion}` : null
|
||||
})
|
||||
const showSharedInstanceUpdateAdmonition = computed(
|
||||
const sharedInstanceUpdateAvailable = computed(
|
||||
() =>
|
||||
sharedInstanceUpdatePreview.value?.updateAvailable === true &&
|
||||
sharedInstanceUpdateKey.value !== hiddenSharedInstanceUpdateKey.value,
|
||||
@@ -515,7 +508,7 @@ async function handleSharedInstanceUnavailable(
|
||||
setSharedInstanceUnavailable(reason)
|
||||
}
|
||||
|
||||
function reviewSharedInstanceUpdate(event: MouseEvent) {
|
||||
function reviewSharedInstanceUpdate(event?: MouseEvent) {
|
||||
const currentInstance = instance.value
|
||||
const preview = sharedInstanceUpdatePreview.value
|
||||
if (
|
||||
@@ -792,6 +785,7 @@ provideInstancePage({
|
||||
instance: instance as ComputedRef<GameInstance>,
|
||||
linkedProject: linkedProjectV3,
|
||||
isServerInstance,
|
||||
sharedInstanceUpdateAvailable,
|
||||
offline,
|
||||
playing,
|
||||
loading,
|
||||
@@ -804,6 +798,7 @@ provideInstancePage({
|
||||
openSettings,
|
||||
browseContent,
|
||||
browseServers,
|
||||
reviewSharedInstanceUpdate,
|
||||
})
|
||||
provideInstanceBackup(() => instance.value!)
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ export function createSharedInstanceContext(
|
||||
enabled: computed(
|
||||
() =>
|
||||
!!instance.value?.id &&
|
||||
instance.value.install_stage === 'installed' &&
|
||||
!!instance.value.shared_instance &&
|
||||
!actionsLocked.value &&
|
||||
!offline.value &&
|
||||
@@ -128,6 +129,7 @@ export function createSharedInstanceContext(
|
||||
const updatePreview = computed(() =>
|
||||
unavailableReason.value ? null : (updatePreviewQuery.data.value ?? null),
|
||||
)
|
||||
const lastUpdateCheckAt = computed(() => updatePreviewQuery.dataUpdatedAt.value || undefined)
|
||||
|
||||
watch(
|
||||
() => instance.value?.id,
|
||||
@@ -162,6 +164,7 @@ export function createSharedInstanceContext(
|
||||
unavailableManager,
|
||||
manager,
|
||||
updatePreview,
|
||||
lastUpdateCheckAt,
|
||||
expectedUserId,
|
||||
wrongAccount,
|
||||
signedOut,
|
||||
|
||||
Reference in New Issue
Block a user