mirror of
https://github.com/MewoLab/AquaDX.git
synced 2025-12-14 11:56:15 +08:00
Feat: Favorites (for all supported games) (#174)
This commit is contained in:
@@ -107,7 +107,8 @@ export interface GenericGameSummary {
|
|||||||
lastVersion: string
|
lastVersion: string
|
||||||
ratingComposition: { [key: string]: any }
|
ratingComposition: { [key: string]: any }
|
||||||
recent: GenericGamePlaylog[]
|
recent: GenericGamePlaylog[]
|
||||||
rival?: boolean
|
rival?: boolean,
|
||||||
|
favorites?: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MusicMeta {
|
export interface MusicMeta {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const EN_REF_USER = {
|
|||||||
'UserHome.RemoveRival': "Remove from Rival",
|
'UserHome.RemoveRival': "Remove from Rival",
|
||||||
'UserHome.InvalidGame': "Game ${game} is not supported on the web UI yet. We only support maimai, chunithm, wacca, and ongeki for now.",
|
'UserHome.InvalidGame': "Game ${game} is not supported on the web UI yet. We only support maimai, chunithm, wacca, and ongeki for now.",
|
||||||
'UserHome.ShowMoreRecent': 'Show more',
|
'UserHome.ShowMoreRecent': 'Show more',
|
||||||
|
'UserHome.FavoriteSongs': 'Favorite Songs'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EN_REF_Welcome = {
|
export const EN_REF_Welcome = {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const zhUser: typeof EN_REF_USER = {
|
|||||||
'UserHome.RemoveRival': "移除劲敌",
|
'UserHome.RemoveRival': "移除劲敌",
|
||||||
'UserHome.InvalidGame': "游戏 ${game} 还不支持网页端查看。我们目前只支持舞萌、中二、华卡和音击。",
|
'UserHome.InvalidGame': "游戏 ${game} 还不支持网页端查看。我们目前只支持舞萌、中二、华卡和音击。",
|
||||||
'UserHome.ShowMoreRecent': "显示更多",
|
'UserHome.ShowMoreRecent': "显示更多",
|
||||||
|
'UserHome.FavoriteSongs': "收藏歌曲"
|
||||||
}
|
}
|
||||||
|
|
||||||
const zhWelcome: typeof EN_REF_Welcome = {
|
const zhWelcome: typeof EN_REF_Welcome = {
|
||||||
|
|||||||
@@ -325,7 +325,6 @@
|
|||||||
<RatingComposition title="Recent 10" comp={d.user.ratingComposition.recent10} {allMusics} game={game != "auto" ? game : "mai2"} top={10}/>
|
<RatingComposition title="Recent 10" comp={d.user.ratingComposition.recent10} {allMusics} game={game != "auto" ? game : "mai2"} top={10}/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
<div class="recent">
|
<div class="recent">
|
||||||
<h2>{t('UserHome.RecentScores')}</h2>
|
<h2>{t('UserHome.RecentScores')}</h2>
|
||||||
<div class="scores">
|
<div class="scores">
|
||||||
@@ -368,6 +367,22 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if d.user.favorites != null && d.user.favorites.length > 0}
|
||||||
|
<div class="favorites">
|
||||||
|
<h2>{t('UserHome.FavoriteSongs')}</h2>
|
||||||
|
<div class="scores">
|
||||||
|
{#each d.user.favorites as favoriteSongId, i}
|
||||||
|
<div>
|
||||||
|
<img src={`${DATA_HOST}/d/${game}/music/00${favoriteSongId.toString().padStart(6, '0').substring(2)}.png`} alt="" on:error={coverNotFound} />
|
||||||
|
<div class="info">
|
||||||
|
<div class="song-title">{allMusics[favoriteSongId.toString()] ? allMusics[favoriteSongId.toString()].name : t("UserHome.UnknownSong")}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<StatusOverlays {error} loading={!d || isLoading} />
|
<StatusOverlays {error} loading={!d || isLoading} />
|
||||||
@@ -554,6 +569,60 @@
|
|||||||
flex-direction: row
|
flex-direction: row
|
||||||
justify-content: space-between
|
justify-content: space-between
|
||||||
|
|
||||||
|
.favorites
|
||||||
|
.scores
|
||||||
|
display: flex
|
||||||
|
flex-wrap: wrap
|
||||||
|
flex-direction: row
|
||||||
|
gap: 20px
|
||||||
|
|
||||||
|
|
||||||
|
// Image and song info
|
||||||
|
> div
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
width: calc(calc(100% / 3) - 20px) // what the fuck is going on anymore
|
||||||
|
gap: 20px
|
||||||
|
|
||||||
|
background-color: rgba(white, 0.03)
|
||||||
|
border-radius: vars.$border-radius
|
||||||
|
|
||||||
|
img
|
||||||
|
width: 50px
|
||||||
|
height: 50px
|
||||||
|
border-radius: vars.$border-radius
|
||||||
|
object-fit: cover
|
||||||
|
|
||||||
|
// Song info and score
|
||||||
|
> div.info
|
||||||
|
flex: 1
|
||||||
|
display: flex
|
||||||
|
justify-content: space-between
|
||||||
|
overflow: hidden
|
||||||
|
flex-direction: column
|
||||||
|
|
||||||
|
.first-line
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
|
||||||
|
// Limit song name to one line
|
||||||
|
.song-title
|
||||||
|
max-width: 100%
|
||||||
|
overflow: hidden
|
||||||
|
text-overflow: ellipsis
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
// Make song score and rank not wrap
|
||||||
|
> div:last-child
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
@media (max-width: vars.$w-mobile)
|
||||||
|
flex-direction: column
|
||||||
|
gap: 0
|
||||||
|
|
||||||
|
.rank-text
|
||||||
|
text-align: left
|
||||||
|
|
||||||
// Recent Scores section
|
// Recent Scores section
|
||||||
.recent
|
.recent
|
||||||
.scores
|
.scores
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ abstract class GameApiController<T : IUserData>(val name: String, userDataClass:
|
|||||||
userMusicRepo.findByUser_Card_ExtIdAndMusicIdIn(card.extId, musicList)
|
userMusicRepo.findByUser_Card_ExtIdAndMusicIdIn(card.extId, musicList)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun genericUserSummary(card: Card, ratingComp: Map<String, String>, rival: Boolean? = null): GenericGameSummary {
|
fun genericUserSummary(card: Card, ratingComp: Map<String, String>, rival: Boolean? = null, favorites: List<Int>? = null): GenericGameSummary {
|
||||||
// Summary values: total plays, player rating, server-wide ranking
|
// Summary values: total plays, player rating, server-wide ranking
|
||||||
// number of each rank, max combo, number of full combo, number of all perfect
|
// number of each rank, max combo, number of full combo, number of all perfect
|
||||||
val user = userDataRepo.findByCard(card) ?: (404 - "Game data not found")
|
val user = userDataRepo.findByCard(card) ?: (404 - "Game data not found")
|
||||||
@@ -199,7 +199,8 @@ abstract class GameApiController<T : IUserData>(val name: String, userDataClass:
|
|||||||
ratingComposition = ratingComp,
|
ratingComposition = ratingComp,
|
||||||
recent = plays.sortedBy { it.userPlayDate.toString() }.takeLast(100).reversed(),
|
recent = plays.sortedBy { it.userPlayDate.toString() }.takeLast(100).reversed(),
|
||||||
lastPlayedHost = user.lastClientId?.let { us.userRepo.findByKeychip(it)?.username },
|
lastPlayedHost = user.lastClientId?.let { us.userRepo.findByKeychip(it)?.username },
|
||||||
rival = rival
|
rival = rival,
|
||||||
|
favorites = favorites
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ data class GenericGameSummary(
|
|||||||
|
|
||||||
val recent: List<IGenericGamePlaylog>,
|
val recent: List<IGenericGamePlaylog>,
|
||||||
|
|
||||||
val rival: Boolean?
|
val rival: Boolean?,
|
||||||
|
val favorites: List<Int>?
|
||||||
)
|
)
|
||||||
|
|
||||||
data class GenericRankingPlayer(
|
data class GenericRankingPlayer(
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ class Chusan(
|
|||||||
"new" to (extra["rating_new_list"] ?: ""),
|
"new" to (extra["rating_new_list"] ?: ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
genericUserSummary(card, ratingComposition)
|
val misc = rp.userMisc.findByUser_Card_ExtId(card.extId).firstOrNull()
|
||||||
|
|
||||||
|
genericUserSummary(card, ratingComposition, null, misc?.favMusic)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class Maimai2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
genericUserSummary(card, ratingComposition, isMyRival)
|
genericUserSummary(card, ratingComposition, isMyRival, extra["favorite_music"]?.split(",")?.mapNotNull{it -> it.toIntOrNull()})
|
||||||
}
|
}
|
||||||
|
|
||||||
@API("user-rating")
|
@API("user-rating")
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ class Wacca(
|
|||||||
|
|
||||||
override suspend fun userSummary(@RP username: String, @RP token: String?) = us.cardByName(username) { card ->
|
override suspend fun userSummary(@RP username: String, @RP token: String?) = us.cardByName(username) { card ->
|
||||||
// TODO: Rating composition
|
// TODO: Rating composition
|
||||||
genericUserSummary(card, mapOf())
|
|
||||||
|
val data = userDataRepo.findByCard_ExtId(card.extId)
|
||||||
|
|
||||||
|
genericUserSummary(card, mapOf(), null, if (data.isPresent) data.get().favoriteSongs else null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val shownRanks: List<Pair<Int, String>> = waccaScores.filter { it.first > 85 * 10000 }
|
override val shownRanks: List<Pair<Int, String>> = waccaScores.filter { it.first > 85 * 10000 }
|
||||||
|
|||||||
Reference in New Issue
Block a user