DATABASE SUPPORT, ARTWORK, and a title display

This commit is contained in:
2026-08-14 12:44:56 -05:00
parent 39850225fc
commit e769d50a68
11 changed files with 534 additions and 16 deletions
+9
View File
@@ -4,6 +4,8 @@ Item {
id: root
property bool highlighted: false
property string title: ""
property url artwork
width: 120
height: 180
@@ -20,5 +22,12 @@ Item {
Rectangle {
anchors.fill: parent
color: "white"
Image {
anchors.fill: parent
source: root.artwork
fillMode: Image.PreserveAspectCrop
}
}
}
+85 -14
View File
@@ -80,17 +80,6 @@ QtObject {
anchors.fill: parent
color: "#181818"
// top text where a menu dock will probably be eventually
Text {
anchors.top: parent.top
anchors.topMargin: 30
anchors.horizontalCenter: parent.horizontalCenter
text: "top placeholder"
color: "white"
font.pixelSize: 24
}
// this is the game carousel. mostly self explanatory, but I wanna point out that the local index for this listView does probably still matter.
// I got rid of dedicated menu indexing for the dock, but I think it still matters here, for the sake of auto-scrolling
ListView {
@@ -117,17 +106,47 @@ QtObject {
leftMargin: 16
rightMargin: 16
model: 20 // this is a placeholder for now, I don't know how I really want to handle max game carousel size yet. another time.
model: gameLibraryModel
// provides the smoothing animation for game selection
// TODO: tune this to make it as nice as possible !!!
NumberAnimation {
id: scrollAnimation
target: gamesList
property: "contentX"
duration: 200
duration: 300
easing.type: Easing.OutCubic
}
function selectCentermostGame() {
let viewCenter = gamesList.width / 2
let bestItem = null
let bestDistance = Infinity
for (let i = 0; i < gamesList.count; i++) {
let item = gamesList.itemAtIndex(i)
// I think offscreen items do not exist
if (!item) {
continue
}
let itemCenter = item.x - gamesList.contentX + item.width / 2
let distance = Math.abs(itemCenter - viewCenter)
if (distance < bestDistance) {
bestDistance = distance
bestItem = item
}
}
if (bestItem) {
navigationManager.focusItem(bestItem)
}
}
// used to scroll to a new game on the game list
function scrollTo(targetX) {
if (Math.abs(targetX - gamesList.contentX) < 0.5) {
@@ -220,12 +239,16 @@ QtObject {
// after flicking, we re-snap the carousel wherever it landed
onMovementEnded: {
gamesList.scrollTo(gamesList.snappedContentX(gamesList.contentX))
gamesList.selectCentermostGame()
}
delegate: GameCard {
id: gameTile
highlighted: navigationManager.currentItem === gameTile
title: model.title
artwork: model.gridArtwork
highlighted: navigationManager.currentItem === gameTile && !gamesList.moving
function onNavigationFocused() {
gamesList.currentIndex = index
@@ -292,6 +315,54 @@ QtObject {
}
}
}
Text {
id: selectedGameTitle
text: gamesList.currentItem ? gamesList.currentItem.title : ""
opacity: (navigationManager.currentItem === gamesList.currentItem && !gamesList.moving) ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
color: "white"
font.pixelSize: 18
elide: Text.ElideRight
horizontalAlignment: Text. AlignHCenter
width: Math.min(implicitWidth, bottomRoot.width - 32)
x: { // we wanna make sure that it centers above the game, except when it's at rest and it's close enough to the edge of the screen that it wont fit
if (!gamesList.currentItem) {
return 16
}
let cardCenter = gamesList.x + gamesList.currentItem.x - gamesList.contentX + gamesList.currentItem.width / 2
let desiredX = cardCenter - width / 2
let minimumX = 16
let maximumX = bottomRoot.width - width - 16
return Math.max(minimumX, Math.min(desiredX, maximumX))
}
Behavior on x {
enabled: !gamesList.moving && !scrollAnimation.running
NumberAnimation {
duration: 100
easing.type: Easing.OutCubic
}
}
anchors.top: gamesList.bottom
anchors.topMargin: 10
}
}
}
}