This commit is contained in:
1 parent
26a29714b2
commit
0af663ac8c
4 files changed
+10452
-10368
No files matched your search
@@ -294,6 +294,9 @@ async function buildPlayer(entry: {
|
|||||||
export function requestSkinSitePlayers(): Promise<SkinSitePlayer[]> {
|
export function requestSkinSitePlayers(): Promise<SkinSitePlayer[]> {
|
||||||
if (playersRequest) return playersRequest
|
if (playersRequest) return playersRequest
|
||||||
if (status.value !== 'signed-in' || !user.value) {
|
if (status.value !== 'signed-in' || !user.value) {
|
||||||
|
// Keep the status meaningful so the UI does not spin forever: an
|
||||||
|
// unauthenticated request means "not loaded yet", not "loading".
|
||||||
|
playersStatus.value = 'idle'
|
||||||
return Promise.reject(new Error('请先登录 StarLight 皮肤站。'))
|
return Promise.reject(new Error('请先登录 StarLight 皮肤站。'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +322,16 @@ export function requestSkinSitePlayers(): Promise<SkinSitePlayer[]> {
|
|||||||
return playersRequest
|
return playersRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop any in-flight or cached player request and fetch again. Used by views
|
||||||
|
* that need to recover after a failed load (e.g. signing in from the skin
|
||||||
|
* page while the first attempt raced the session check).
|
||||||
|
*/
|
||||||
|
export function reloadSkinSitePlayers(): Promise<SkinSitePlayer[]> {
|
||||||
|
playersRequest = null
|
||||||
|
return requestSkinSitePlayers()
|
||||||
|
}
|
||||||
|
|
||||||
export function selectSkinSitePlayer(playerId: string | null) {
|
export function selectSkinSitePlayer(playerId: string | null) {
|
||||||
if (playerId === null) {
|
if (playerId === null) {
|
||||||
selectedPlayerId.value = null
|
selectedPlayerId.value = null
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -39,6 +39,7 @@ import SkinListSkeleton from '@/components/ui/skin/SkinListSkeleton.vue'
|
|||||||
import VirtualSkinSectionList from '@/components/ui/skin/VirtualSkinSectionList.vue'
|
import VirtualSkinSectionList from '@/components/ui/skin/VirtualSkinSectionList.vue'
|
||||||
import {
|
import {
|
||||||
openSkinSiteLogin,
|
openSkinSiteLogin,
|
||||||
|
reloadSkinSitePlayers,
|
||||||
requestSkinSitePlayers,
|
requestSkinSitePlayers,
|
||||||
requestSkinSiteSkinUpdate,
|
requestSkinSiteSkinUpdate,
|
||||||
selectedSkinSitePlayerId,
|
selectedSkinSitePlayerId,
|
||||||
@@ -214,6 +215,18 @@ const messages = defineMessages({
|
|||||||
id: 'app.skins.skin-site-account.empty-description',
|
id: 'app.skins.skin-site-account.empty-description',
|
||||||
defaultMessage: 'This skin site account does not have an available player profile yet.',
|
defaultMessage: 'This skin site account does not have an available player profile yet.',
|
||||||
},
|
},
|
||||||
|
errorSkinSitePlayersTitle: {
|
||||||
|
id: 'app.skins.skin-site-account.error-title',
|
||||||
|
defaultMessage: 'Could not load your players',
|
||||||
|
},
|
||||||
|
errorSkinSitePlayersDescription: {
|
||||||
|
id: 'app.skins.skin-site-account.error-description',
|
||||||
|
defaultMessage: 'Check your connection and try again.',
|
||||||
|
},
|
||||||
|
retryButton: {
|
||||||
|
id: 'app.skins.skin-site-account.retry',
|
||||||
|
defaultMessage: 'Retry',
|
||||||
|
},
|
||||||
offlineCompatibility: {
|
offlineCompatibility: {
|
||||||
id: 'app.skins.offline-account.compatibility',
|
id: 'app.skins.offline-account.compatibility',
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
@@ -982,6 +995,37 @@ watch(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Load the player list whenever the session becomes available or the view is
|
||||||
|
// opened while the list never started loading. Without this the skin page can
|
||||||
|
// sit on "loading" forever when the first request raced the session check.
|
||||||
|
function ensureSkinSitePlayersLoaded() {
|
||||||
|
if (!skinSiteUser.value) return
|
||||||
|
if (skinSitePlayersStatus.value === 'checking') return
|
||||||
|
if (skinSitePlayersStatus.value === 'ready' && skinSitePlayers.value.length) return
|
||||||
|
if (skinSitePlayersStatus.value === 'error') return
|
||||||
|
void reloadSkinSitePlayers().catch((error) => {
|
||||||
|
console.warn('Failed to load skin site players:', error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [skinSiteUser.value?.uuid, skinSiteStatus.value] as const,
|
||||||
|
([uuid, sessionStatus]) => {
|
||||||
|
if (uuid && sessionStatus === 'signed-in') ensureSkinSitePlayersLoaded()
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(skinSitePlayersStatus, (value) => {
|
||||||
|
if (value === 'idle' && skinSiteUser.value) ensureSkinSitePlayersLoaded()
|
||||||
|
})
|
||||||
|
|
||||||
|
function retrySkinSitePlayers() {
|
||||||
|
void reloadSkinSitePlayers().catch((error) => {
|
||||||
|
console.warn('Failed to reload skin site players:', error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function getBakedSkinTextures(skin: Skin): RenderResult | undefined {
|
function getBakedSkinTextures(skin: Skin): RenderResult | undefined {
|
||||||
const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
|
const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
|
||||||
return skinBlobUrlMap.get(key)
|
return skinBlobUrlMap.get(key)
|
||||||
@@ -1436,22 +1480,26 @@ await loadSkins()
|
|||||||
<h1 class="text-3xl font-extrabold m-0">
|
<h1 class="text-3xl font-extrabold m-0">
|
||||||
{{
|
{{
|
||||||
formatMessage(
|
formatMessage(
|
||||||
skinSiteUser
|
!skinSiteUser
|
||||||
? skinSitePlayersStatus === 'checking' || skinSitePlayersStatus === 'idle'
|
? messages.signInTitle
|
||||||
? messages.loadingSkinSitePlayersTitle
|
: skinSitePlayersStatus === 'error'
|
||||||
: messages.noSkinSitePlayersTitle
|
? messages.errorSkinSitePlayersTitle
|
||||||
: messages.signInTitle,
|
: skinSitePlayersStatus === 'checking' || skinSitePlayersStatus === 'idle'
|
||||||
|
? messages.loadingSkinSitePlayersTitle
|
||||||
|
: messages.noSkinSitePlayersTitle,
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-lg m-0">
|
<p class="text-lg m-0">
|
||||||
{{
|
{{
|
||||||
formatMessage(
|
formatMessage(
|
||||||
skinSiteUser
|
!skinSiteUser
|
||||||
? skinSitePlayersStatus === 'checking' || skinSitePlayersStatus === 'idle'
|
? messages.signInDescription
|
||||||
? messages.loadingSkinSitePlayersDescription
|
: skinSitePlayersStatus === 'error'
|
||||||
: messages.noSkinSitePlayersDescription
|
? messages.errorSkinSitePlayersDescription
|
||||||
: messages.signInDescription,
|
: skinSitePlayersStatus === 'checking' || skinSitePlayersStatus === 'idle'
|
||||||
|
? messages.loadingSkinSitePlayersDescription
|
||||||
|
: messages.noSkinSitePlayersDescription,
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
@@ -1462,6 +1510,11 @@ await loadSkins()
|
|||||||
"
|
"
|
||||||
class="h-8 w-8 animate-spin text-brand"
|
class="h-8 w-8 animate-spin text-brand"
|
||||||
/>
|
/>
|
||||||
|
<ButtonStyled v-if="skinSiteUser && skinSitePlayersStatus === 'error'" color="brand">
|
||||||
|
<button @click="retrySkinSitePlayers">
|
||||||
|
{{ formatMessage(messages.retryButton) }}
|
||||||
|
</button>
|
||||||
|
</ButtonStyled>
|
||||||
<ButtonStyled v-if="!offline && !skinSiteUser" color="brand">
|
<ButtonStyled v-if="!offline && !skinSiteUser" color="brand">
|
||||||
<button @click="loginToSkinSite">
|
<button @click="loginToSkinSite">
|
||||||
<LogInIcon />
|
<LogInIcon />
|
||||||
|
|||||||
Reference in new issue
Block a user