Skip to content

Commit 029aee2

Browse files
committed
fix some game doesn't show up
1 parent 55ba2d7 commit 029aee2

7 files changed

Lines changed: 205 additions & 30 deletions

File tree

src/mainwindow.cpp

Lines changed: 122 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -214,15 +214,21 @@ void MainWindow::startSync() {
214214
m_syncWorker->start();
215215
}
216216

217-
void MainWindow::onSyncDone(QSet<QString> appIds) {
218-
m_cachedAppIds = appIds;
217+
void MainWindow::onSyncDone(QList<GameInfo> games) {
218+
m_supportedGames = games;
219219
m_spinner->stop();
220220
m_stack->setCurrentIndex(1); // List
221-
m_statusLabel->setText(QString("Online • %L1 supported games")
222-
.arg(appIds.size()));
221+
m_statusLabel->setText(QString("Online • %1 supported games")
222+
.arg(games.size()));
223223
m_searchInput->setFocus();
224+
225+
// Trigger initial empty search to show list if needed, or just clear
226+
if (!m_searchInput->text().isEmpty()) {
227+
doSearch();
228+
}
224229
}
225230

231+
226232
void MainWindow::onSyncError(QString error) {
227233
m_spinner->stop();
228234
m_stack->setCurrentIndex(1);
@@ -245,8 +251,24 @@ void MainWindow::doSearch() {
245251
if (query.isEmpty()) return;
246252

247253
m_currentSearchId++;
248-
m_statusLabel->setText("Searching Store...");
254+
m_statusLabel->setText("Searching...");
255+
256+
// 1. Local Search (Instant)
257+
QJsonArray localResults;
258+
for (const auto& game : m_supportedGames) {
259+
if (game.name.contains(query, Qt::CaseInsensitive) || game.id == query) {
260+
QJsonObject item;
261+
item["id"] = game.id;
262+
item["name"] = game.name;
263+
item["supported_local"] = true; // Marker for local result
264+
localResults.append(item);
265+
}
266+
}
267+
268+
// Display local results immediately
269+
displayResults(localResults);
249270

271+
// 2. Remote Search (Fallback/Supplement)
250272
if (m_activeReply) {
251273
m_activeReply->abort();
252274
}
@@ -263,26 +285,99 @@ void MainWindow::doSearch() {
263285
m_activeReply->setProperty("sid", m_currentSearchId);
264286
}
265287

288+
266289
void MainWindow::onSearchFinished(QNetworkReply* reply) {
267290
reply->deleteLater();
268291
m_activeReply = nullptr;
269292

270293
if (reply->error() == QNetworkReply::OperationCanceledError) return;
271-
if (reply->property("sid").toInt() != m_currentSearchId) return;
294+
int sid = reply->property("sid").toInt();
295+
if (sid != m_currentSearchId) return;
272296

273297
if (reply->error() != QNetworkReply::NoError) {
274-
m_statusLabel->setText("Search failed");
298+
// Don't clear list if we have local results
299+
if (m_resultsList->count() == 0) {
300+
m_statusLabel->setText("Store search failed");
301+
}
275302
return;
276303
}
277304

278305
QByteArray data = reply->readAll();
279306
QJsonDocument doc = QJsonDocument::fromJson(data);
280307
QJsonObject obj = doc.object();
281-
QJsonArray items = obj["items"].toArray();
308+
QJsonArray remoteItems = obj["items"].toArray();
309+
310+
// Merge remote items with existing local items
311+
// We strictly prefer local items because they are known supported
312+
313+
QSet<QString> existingIds;
314+
for (int i = 0; i < m_resultsList->count(); ++i) {
315+
QMap<QString, QString> data = m_resultsList->item(i)->data(Qt::UserRole).value<QMap<QString, QString>>();
316+
existingIds.insert(data["appid"]);
317+
}
318+
319+
bool addedRemote = false;
320+
QJsonArray mergedItems;
321+
322+
// Re-add existing (local) items to the list to keep order or just append new ones?
323+
// Let's just append new remote ones for now to avoid flickering
282324

283-
displayResults(items);
325+
QList<QJsonObject> newItems;
326+
for (const QJsonValue& val : remoteItems) {
327+
QJsonObject item = val.toObject();
328+
QString id = QString::number(item["id"].toInt());
329+
330+
if (!existingIds.contains(id)) {
331+
newItems.append(item);
332+
addedRemote = true;
333+
}
334+
}
335+
336+
if (addedRemote) {
337+
// Append to UI
338+
for (const auto& item : newItems) {
339+
QString name = item["name"].toString("Unknown");
340+
QString appid = QString::number(item["id"].toInt());
341+
342+
// Check support again (in case it's in our support list but wasn't found by local string match?)
343+
// Although local search should have found it if name matched.
344+
// But maybe name in steam api differs from our index.
345+
346+
bool supported = false;
347+
for(const auto& g : m_supportedGames) {
348+
if(g.id == appid) {
349+
supported = true;
350+
break;
351+
}
352+
}
353+
354+
QString statusText = supported ? "Supported" : "Not Indexed";
355+
QString displayText = QString("%1\n%2 • ID: %3")
356+
.arg(name).arg(statusText).arg(appid);
357+
358+
QListWidgetItem* listItem = new QListWidgetItem(displayText);
359+
360+
QMap<QString, QString> data;
361+
data["name"] = name;
362+
data["appid"] = appid;
363+
data["supported"] = supported ? "true" : "false";
364+
listItem->setData(Qt::UserRole, QVariant::fromValue(data));
365+
366+
listItem->setIcon(createStatusIcon(supported));
367+
368+
if (supported) {
369+
listItem->setForeground(Colors::toQColor(Colors::ACCENT_GREEN));
370+
} else {
371+
listItem->setForeground(Colors::toQColor(Colors::TEXT_SECONDARY));
372+
}
373+
374+
m_resultsList->addItem(listItem);
375+
}
376+
m_statusLabel->setText(QString("Found %1 results").arg(m_resultsList->count()));
377+
}
284378
}
285379

380+
286381
QIcon MainWindow::createStatusIcon(bool supported) {
287382
int size = 64;
288383
QPixmap pixmap(size, size);
@@ -323,15 +418,29 @@ void MainWindow::displayResults(const QJsonArray& items) {
323418
m_btnPatch->setEnabled(false);
324419

325420
if (items.isEmpty()) {
326-
m_statusLabel->setText("No results found");
327-
return;
421+
// m_statusLabel->setText("No results found"); // Don't show this yet, might be waiting for remote
422+
return;
328423
}
329424

330425
for (const QJsonValue& val : items) {
331426
QJsonObject item = val.toObject();
332427
QString name = item["name"].toString("Unknown");
333-
QString appid = QString::number(item["id"].toInt());
334-
bool supported = m_cachedAppIds.contains(appid);
428+
QString appid = item.contains("id") ? (item["id"].isString() ? item["id"].toString() : QString::number(item["id"].toInt())) : "0";
429+
bool supported = false;
430+
431+
// If it came from local search, we know it's supported
432+
if (item.contains("supported_local")) {
433+
supported = true;
434+
} else {
435+
// Double check
436+
for(const auto& g : m_supportedGames) {
437+
if(g.id == appid) {
438+
supported = true;
439+
break;
440+
}
441+
}
442+
}
443+
335444

336445
QString statusText = supported ? "Supported" : "Not Indexed";
337446
QString displayText = QString("%1\n%2 • ID: %3")

src/mainwindow.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
#include <QNetworkReply>
1616

1717
class GlassButton;
18+
#include "utils/gameinfo.h"
19+
1820
class LoadingSpinner;
1921
class IndexDownloadWorker;
22+
2023
class LuaDownloadWorker;
2124
class RestartWorker;
2225

@@ -31,7 +34,8 @@ class MainWindow : public QMainWindow {
3134
void paintEvent(QPaintEvent* event) override;
3235

3336
private slots:
34-
void onSyncDone(QSet<QString> appIds);
37+
void onSyncDone(QList<GameInfo> games);
38+
3539
void onSyncError(QString error);
3640
void onSearchChanged(const QString& text);
3741
void doSearch();
@@ -59,7 +63,8 @@ private slots:
5963
GlassButton* m_btnRestart;
6064

6165
// Data
62-
QSet<QString> m_cachedAppIds;
66+
QList<GameInfo> m_supportedGames;
67+
6368
QMap<QString, QString> m_selectedGame; // name, appid, supported
6469

6570
// Network

src/utils/gameinfo.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef GAMEINFO_H
2+
#define GAMEINFO_H
3+
4+
#include <QString>
5+
6+
struct GameInfo {
7+
QString id;
8+
QString name;
9+
10+
bool operator==(const GameInfo& other) const {
11+
return id == other.id;
12+
}
13+
14+
// For QSet or hashing if needed later
15+
friend uint qHash(const GameInfo& key, uint seed = 0) {
16+
return qHash(key.id, seed);
17+
}
18+
};
19+
20+
#endif // GAMEINFO_H

src/workers/indexdownloadworker.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,16 @@ void IndexDownloadWorker::run() {
7676
reply->deleteLater();
7777

7878
// Extract app IDs
79-
QSet<QString> appIds;
80-
QJsonArray arr = indexData["app_ids"].toArray();
79+
// Extract games
80+
QList<GameInfo> games;
81+
QJsonArray arr = indexData["games"].toArray();
8182
for (const QJsonValue& val : arr) {
82-
appIds.insert(val.toString());
83+
QJsonObject obj = val.toObject();
84+
games.append({obj["id"].toString(), obj["name"].toString()});
8385
}
8486

85-
emit finished(appIds);
87+
emit finished(games);
88+
8689

8790
} catch (const std::exception& e) {
8891
emit error(QString::fromStdString(e.what()));

src/workers/indexdownloadworker.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <QThread>
55
#include <QSet>
6+
#include "../utils/gameinfo.h"
7+
68
#include <QString>
79

810
class IndexDownloadWorker : public QThread {
@@ -12,7 +14,8 @@ class IndexDownloadWorker : public QThread {
1214
explicit IndexDownloadWorker(QObject* parent = nullptr);
1315

1416
signals:
15-
void finished(QSet<QString> appIds);
17+
void finished(QList<GameInfo> games);
18+
1619
void progress(QString message);
1720
void error(QString errorMessage);
1821

webserver/generate_index.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,72 @@
11
"""
22
Generate games_index.json from all Lua files in the games directory.
33
This script is run by the GitHub Actions workflow on each push.
4+
It fetches game names from the Steam API to create a rich index.
45
"""
56

67
import os
78
import json
9+
import requests
10+
import time
811

12+
STEAM_APP_LIST_URL = "http://api.steampowered.com/ISteamApps/GetAppList/v2"
13+
14+
def get_steam_app_map():
15+
"""Fetch all steam apps and return a dict of {app_id: name}."""
16+
try:
17+
print("Fetching Steam App List...")
18+
response = requests.get(STEAM_APP_LIST_URL, timeout=30)
19+
response.raise_for_status()
20+
data = response.json()
21+
22+
app_map = {}
23+
for app in data['applist']['apps']:
24+
app_map[str(app['appid'])] = app['name']
25+
26+
print(f"Fetched {len(app_map)} apps from Steam.")
27+
return app_map
28+
except Exception as e:
29+
print(f"Error fetching Steam App List: {e}")
30+
return {}
931

1032
def generate_index():
11-
"""Scan games directory and generate JSON index of all app IDs."""
33+
"""Scan games directory and generate JSON index of all supported games with names."""
1234
games_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'games')
1335

14-
app_ids = []
36+
# Get mapping of AppID -> Name
37+
app_map = get_steam_app_map()
38+
39+
games_list = []
1540

1641
if os.path.exists(games_dir):
1742
for filename in os.listdir(games_dir):
1843
if filename.endswith('.lua'):
1944
# Extract app ID from filename (e.g., "730.lua" -> "730")
2045
app_id = filename[:-4]
21-
app_ids.append(app_id)
46+
47+
# Get name from map, or fallback to generic
48+
name = app_map.get(app_id, f"Unknown Game ({app_id})")
49+
50+
games_list.append({
51+
"id": app_id,
52+
"name": name
53+
})
2254

23-
# Sort for consistent output
24-
app_ids.sort(key=lambda x: int(x) if x.isdigit() else 0)
55+
# Sort by name for easier reading, though client might resort
56+
games_list.sort(key=lambda x: x['name'])
2557

2658
index_data = {
27-
'app_ids': app_ids,
28-
'count': len(app_ids)
59+
'games': games_list,
60+
'count': len(games_list),
61+
'last_updated': int(time.time())
2962
}
3063

3164
# Write to root of webserver folder
3265
output_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'games_index.json')
33-
with open(output_path, 'w') as f:
34-
json.dump(index_data, f)
66+
with open(output_path, 'w', encoding='utf-8') as f:
67+
json.dump(index_data, f, ensure_ascii=False, indent=2)
3568

36-
print(f"Generated games_index.json with {len(app_ids)} app IDs")
69+
print(f"Generated games_index.json with {len(games_list)} supported games.")
3770
return output_path
3871

3972

webserver/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
Flask
22
gunicorn
3+
requests
4+

0 commit comments

Comments
 (0)