feat:添加了启动进度的显示
Some checks failed
Axolotl desktop CI / guardrails (push) Has been cancelled
Axolotl desktop CI / desktop (macos-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (ubuntu-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (windows-latest) (push) Has been cancelled
Axolotl desktop CI / website (push) Has been cancelled
Repository checks / typos (push) Has been cancelled
Repository checks / tombi (push) Has been cancelled
Rust checks / shear (push) Has been cancelled
Sync source to CNB / Sync Git ref (push) Has been cancelled
Some checks failed
Axolotl desktop CI / guardrails (push) Has been cancelled
Axolotl desktop CI / desktop (macos-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (ubuntu-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (windows-latest) (push) Has been cancelled
Axolotl desktop CI / website (push) Has been cancelled
Repository checks / typos (push) Has been cancelled
Repository checks / tombi (push) Has been cancelled
Rust checks / shear (push) Has been cancelled
Sync source to CNB / Sync Git ref (push) Has been cancelled
This commit is contained in:
108
apps/app-frontend/src/components/home/HomeLaunchProgress.vue
Normal file
108
apps/app-frontend/src/components/home/HomeLaunchProgress.vue
Normal file
@ -0,0 +1,108 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DownloadIcon } from '@modrinth/assets'
|
||||
import { defineMessages, useVIntl } from '@modrinth/ui'
|
||||
import { computed, onUnmounted, ref } from 'vue'
|
||||
|
||||
import { loading_listener } from '@/helpers/events'
|
||||
import type { LoadingBar } from '@/helpers/state'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'app.home.launch-progress.title', defaultMessage: '启动进度' },
|
||||
empty: { id: 'app.home.launch-progress.empty', defaultMessage: '启动游戏后,这里会显示进度。' },
|
||||
})
|
||||
|
||||
interface LoadingEventPayload {
|
||||
event: LoadingBar['bar_type']
|
||||
loader_uuid: string
|
||||
fraction: number | null
|
||||
message: string
|
||||
}
|
||||
|
||||
interface LaunchProgressItem {
|
||||
key: string
|
||||
message: string
|
||||
fraction: number | null
|
||||
}
|
||||
|
||||
// 启动相关(以及准备)阶段会发的 loading 类型;安装/下载也一并显示,便于用户看到进度
|
||||
const LAUNCH_BAR_TYPES = new Set([
|
||||
'minecraft_download',
|
||||
'instance_update',
|
||||
'zip_extract',
|
||||
'pack_download',
|
||||
'pack_file_download',
|
||||
])
|
||||
|
||||
const progressItems = ref<LaunchProgressItem[]>([])
|
||||
const activeMap = new Map<string, LaunchProgressItem>()
|
||||
|
||||
function isVisible(barType: LoadingBar['bar_type']): boolean {
|
||||
const type = barType?.type ?? ''
|
||||
return LAUNCH_BAR_TYPES.has(type)
|
||||
}
|
||||
|
||||
function applyEvent(payload: LoadingEventPayload) {
|
||||
// fraction 为 null 约定为「完成」,移除该进度条
|
||||
if (payload.fraction === null) {
|
||||
activeMap.delete(payload.loader_uuid)
|
||||
progressItems.value = Array.from(activeMap.values())
|
||||
return
|
||||
}
|
||||
if (!isVisible(payload.event)) return
|
||||
|
||||
activeMap.set(payload.loader_uuid, {
|
||||
key: payload.loader_uuid,
|
||||
message: payload.message,
|
||||
fraction: payload.fraction,
|
||||
})
|
||||
progressItems.value = Array.from(activeMap.values())
|
||||
}
|
||||
|
||||
const hasProgress = computed(() => progressItems.value.length > 0)
|
||||
|
||||
function percent(item: LaunchProgressItem): string {
|
||||
if (item.fraction == null || !Number.isFinite(item.fraction)) return ''
|
||||
return `${Math.round(Math.max(0, Math.min(1, item.fraction)) * 100)}%`
|
||||
}
|
||||
|
||||
const unlistenLoading = await loading_listener((payload: LoadingEventPayload) => {
|
||||
applyEvent(payload)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
unlistenLoading?.()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section
|
||||
v-if="hasProgress"
|
||||
class="flex min-w-0 flex-col gap-3 border-0 border-b-[1px] border-solid border-[--brand-gradient-border] p-4"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<DownloadIcon class="size-4 shrink-0 text-secondary" aria-hidden="true" />
|
||||
<h2 class="m-0 truncate text-lg">
|
||||
{{ formatMessage(messages.title) }}
|
||||
</h2>
|
||||
</div>
|
||||
<ul class="m-0 flex list-none flex-col gap-2 p-0">
|
||||
<li v-for="item in progressItems" :key="item.key" class="flex min-w-0 flex-col gap-1">
|
||||
<div class="flex min-w-0 items-center justify-between gap-2 text-sm text-primary">
|
||||
<span class="min-w-0 truncate">{{ item.message }}</span>
|
||||
<span v-if="percent(item)" class="shrink-0 tabular-nums text-secondary">
|
||||
{{ percent(item) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="h-1 w-full overflow-hidden rounded-full bg-surface-4">
|
||||
<div
|
||||
class="h-full rounded-full bg-brand transition-[width] duration-200"
|
||||
:style="{ width: percent(item) || '100%' }"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</template>
|
||||
Reference in New Issue
Block a user