@@ -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+
226232void 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+
266289void 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+
286381QIcon 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" )
0 commit comments