diff --git a/src/LuaToolsGui/Models/FixModels.cs b/src/LuaToolsGui/Models/FixModels.cs index 2921ce0..7b53191 100644 --- a/src/LuaToolsGui/Models/FixModels.cs +++ b/src/LuaToolsGui/Models/FixModels.cs @@ -56,3 +56,36 @@ public class DenuvoDownloadResponse { [JsonPropertyName("url")] public string Url { get; set; } = ""; } + +// ── Supabase REST (direct, anon) — the recently-added fixes feed ───── +// There's no /api/denuvo "recent" endpoint, so the Fixes page's "Recent" tab reads the public +// `denuvo_fixes` table straight from PostgREST (same pattern as GetStandardUsageAsync reading +// `user_downloads`). Each row comes with its game and tags embedded. + +public class DenuvoRecentFix +{ + [JsonPropertyName("id")] public string Id { get; set; } = ""; + [JsonPropertyName("appid")] public string AppId { get; set; } = ""; + [JsonPropertyName("title")] public string Title { get; set; } = ""; + [JsonPropertyName("description")] public string? Description { get; set; } + [JsonPropertyName("created_at")] public string? CreatedAt { get; set; } + [JsonPropertyName("denuvo_games")] public DenuvoRecentGame? Game { get; set; } + [JsonPropertyName("denuvo_fix_tags")] public List FixTags { get; set; } = []; + + /// The fix's tags, flattened from the denuvo_fix_tags → denuvo_tags embed. + [JsonIgnore] + public IReadOnlyList Tags => + FixTags.Where(t => t.Tag is not null).Select(t => t.Tag!).ToList(); +} + +public class DenuvoRecentGame +{ + [JsonPropertyName("name")] public string? Name { get; set; } + [JsonPropertyName("header_image")] public string? HeaderImage { get; set; } +} + +public class DenuvoRecentFixTag +{ + [JsonPropertyName("tag_id")] public string TagId { get; set; } = ""; + [JsonPropertyName("denuvo_tags")] public DenuvoTag? Tag { get; set; } +} diff --git a/src/LuaToolsGui/Resources/Strings.Designer.cs b/src/LuaToolsGui/Resources/Strings.Designer.cs index 226b9b5..e0e27dc 100644 --- a/src/LuaToolsGui/Resources/Strings.Designer.cs +++ b/src/LuaToolsGui/Resources/Strings.Designer.cs @@ -301,6 +301,11 @@ public static class Strings public static string Fixes_Toast_CouldntApply => Get(nameof(Fixes_Toast_CouldntApply)); public static string Fixes_Toast_Refreshed_Title => Get(nameof(Fixes_Toast_Refreshed_Title)); public static string Fixes_Toast_Refreshed_Body => Get(nameof(Fixes_Toast_Refreshed_Body)); + public static string Fixes_Tab_Games => Get(nameof(Fixes_Tab_Games)); + public static string Fixes_Tab_Recent => Get(nameof(Fixes_Tab_Recent)); + public static string Fixes_New => Get(nameof(Fixes_New)); + public static string Fixes_Recent_Empty => Get(nameof(Fixes_Recent_Empty)); + public static string Fixes_Recent_Err_Load => Get(nameof(Fixes_Recent_Err_Load)); // ── Add / Download ── public static string Add_Title => Get(nameof(Add_Title)); diff --git a/src/LuaToolsGui/Resources/Strings.ar.resx b/src/LuaToolsGui/Resources/Strings.ar.resx index 3af59fe..1cb0707 100644 --- a/src/LuaToolsGui/Resources/Strings.ar.resx +++ b/src/LuaToolsGui/Resources/Strings.ar.resx @@ -553,4 +553,9 @@ لقد بلغت حدّك اليومي في Hubcap. لا يوجد بيان Hubcap متاح لهذا التطبيق. فشل التنزيل من Hubcap ({0}). + ألعاب + الأحدث + جديد + لا توجد إصلاحات صدرت مؤخرًا. + تعذّر تحميل الإصلاحات الحديثة. تحقق من اتصالك. diff --git a/src/LuaToolsGui/Resources/Strings.bg.resx b/src/LuaToolsGui/Resources/Strings.bg.resx index 8beb744..5cac78f 100644 --- a/src/LuaToolsGui/Resources/Strings.bg.resx +++ b/src/LuaToolsGui/Resources/Strings.bg.resx @@ -527,4 +527,9 @@ Достигна дневния си лимит за Hubcap. Няма наличен Hubcap манифест за това приложение. Изтеглянето от Hubcap е неуспешно ({0}). + Игри + Скорошни + Ново + Наскоро не са излизали корекции. + Скорошните корекции не можаха да се заредят. Проверете връзката си. diff --git a/src/LuaToolsGui/Resources/Strings.cs.resx b/src/LuaToolsGui/Resources/Strings.cs.resx index 02628a1..37b769f 100644 --- a/src/LuaToolsGui/Resources/Strings.cs.resx +++ b/src/LuaToolsGui/Resources/Strings.cs.resx @@ -527,4 +527,9 @@ Tím se smažou soubory .lua ze Steam\config\stplug-in. Poté restartujte Steam, Dosáhl jsi denního limitu Hubcap. Pro tuto aplikaci není dostupný žádný manifest Hubcap. Stahování z Hubcap selhalo ({0}). + Hry + Nedávné + Nové + Žádné nedávné opravy. + Nedávné opravy se nepodařilo načíst. Zkontrolujte připojení. diff --git a/src/LuaToolsGui/Resources/Strings.da.resx b/src/LuaToolsGui/Resources/Strings.da.resx index dd41f7e..26d05fe 100644 --- a/src/LuaToolsGui/Resources/Strings.da.resx +++ b/src/LuaToolsGui/Resources/Strings.da.resx @@ -527,4 +527,9 @@ Dette sletter .lua-filerne fra Steam\config\stplug-in. Genstart Steam bagefter, Du har nået din daglige Hubcap-grænse. Der er ingen Hubcap-manifest til denne app. Hubcap-download mislykkedes ({0}). + Spil + Seneste + Ny + Ingen nylige rettelser. + Kunne ikke indlæse nylige rettelser. Tjek din forbindelse. diff --git a/src/LuaToolsGui/Resources/Strings.de.resx b/src/LuaToolsGui/Resources/Strings.de.resx index d973386..fa0facc 100644 --- a/src/LuaToolsGui/Resources/Strings.de.resx +++ b/src/LuaToolsGui/Resources/Strings.de.resx @@ -527,4 +527,9 @@ Dadurch werden die .lua-Dateien aus Steam\config\stplug-in gelöscht. Starte Ste Dein tägliches Hubcap-Limit ist erreicht. Für diese App ist kein Hubcap-Manifest verfügbar. Hubcap-Download fehlgeschlagen ({0}). + Spiele + Neueste + Neu + Noch keine neuen Fixes. + Neue Fixes konnten nicht geladen werden. Überprüfe deine Verbindung. diff --git a/src/LuaToolsGui/Resources/Strings.el.resx b/src/LuaToolsGui/Resources/Strings.el.resx index b22e08e..852fb99 100644 --- a/src/LuaToolsGui/Resources/Strings.el.resx +++ b/src/LuaToolsGui/Resources/Strings.el.resx @@ -527,4 +527,9 @@ Έφτασες το ημερήσιο όριο του Hubcap. Δεν υπάρχει διαθέσιμο manifest Hubcap για αυτήν την εφαρμογή. Η λήψη από το Hubcap απέτυχε ({0}). + Παιχνίδια + Πρόσφατα + Νέο + Δεν κυκλοφόρησαν πρόσφατες διορθώσεις. + Δεν ήταν δυνατή η φόρτωση των πρόσφατων διορθώσεων. Ελέγξτε τη σύνδεσή σας. diff --git a/src/LuaToolsGui/Resources/Strings.es-419.resx b/src/LuaToolsGui/Resources/Strings.es-419.resx index e4c9cdd..1e09e42 100644 --- a/src/LuaToolsGui/Resources/Strings.es-419.resx +++ b/src/LuaToolsGui/Resources/Strings.es-419.resx @@ -527,4 +527,9 @@ Esto borra los archivos .lua de Steam\config\stplug-in. Reinicia Steam después Llegaste a tu límite diario de Hubcap. No hay ningún manifiesto de Hubcap para esta app. Falló la descarga de Hubcap ({0}). + Juegos + Recientes + Nuevo + No hay parches publicados recientemente. + No se pudieron cargar los parches recientes. Comprueba tu conexión. diff --git a/src/LuaToolsGui/Resources/Strings.es.resx b/src/LuaToolsGui/Resources/Strings.es.resx index fa80ede..6002126 100644 --- a/src/LuaToolsGui/Resources/Strings.es.resx +++ b/src/LuaToolsGui/Resources/Strings.es.resx @@ -527,4 +527,9 @@ Esto borra los archivos .lua de Steam\config\stplug-in. Reinicia Steam después Has alcanzado tu límite diario de Hubcap. No hay ningún manifiesto de Hubcap para esta app. Error en la descarga de Hubcap ({0}). + Juegos + Recientes + Nuevo + No hay parches publicados recientemente. + No se pudieron cargar los parches recientes. Comprueba tu conexión. diff --git a/src/LuaToolsGui/Resources/Strings.fi.resx b/src/LuaToolsGui/Resources/Strings.fi.resx index 5b55eee..4e0b229 100644 --- a/src/LuaToolsGui/Resources/Strings.fi.resx +++ b/src/LuaToolsGui/Resources/Strings.fi.resx @@ -527,4 +527,9 @@ Tämä poistaa .lua-tiedostot sijainnista Steam\config\stplug-in. Käynnistä St Päivittäinen Hubcap-rajasi on täynnä. Tälle sovellukselle ei ole Hubcap-manifestia. Hubcap-lataus epäonnistui ({0}). + Pelit + Uusimmat + Uusi + Ei viimeaikaisia korjauksia. + Uusimpia korjauksia ei voitu ladata. Tarkista yhteytesi. diff --git a/src/LuaToolsGui/Resources/Strings.fr.resx b/src/LuaToolsGui/Resources/Strings.fr.resx index 4ac684c..a58b7d7 100644 --- a/src/LuaToolsGui/Resources/Strings.fr.resx +++ b/src/LuaToolsGui/Resources/Strings.fr.resx @@ -527,4 +527,9 @@ Cela supprime les fichiers .lua de Steam\config\stplug-in. Redémarrez Steam ens Ta limite quotidienne Hubcap est atteinte. Aucun manifeste Hubcap n'est disponible pour cette app. Échec du téléchargement Hubcap ({0}). + Jeux + Récents + Nouveau + Aucun correctif publié récemment. + Impossible de charger les correctifs récents. Vérifiez votre connexion. diff --git a/src/LuaToolsGui/Resources/Strings.hu.resx b/src/LuaToolsGui/Resources/Strings.hu.resx index d49b066..98693f5 100644 --- a/src/LuaToolsGui/Resources/Strings.hu.resx +++ b/src/LuaToolsGui/Resources/Strings.hu.resx @@ -527,4 +527,9 @@ Ez törli a .lua fájlokat a Steam\config\stplug-in mappából. Ezután indítsd Elérted a napi Hubcap-korlátot. Ehhez az alkalmazáshoz nincs Hubcap-manifeszt. A Hubcap-letöltés sikertelen ({0}). + Játékok + Legutóbbiak + Új + Nincs mostanában megjelent javítás. + A legutóbbi javítások betöltése nem sikerült. Ellenőrizd a kapcsolatot. diff --git a/src/LuaToolsGui/Resources/Strings.id.resx b/src/LuaToolsGui/Resources/Strings.id.resx index a54a53a..2c3e5a0 100644 --- a/src/LuaToolsGui/Resources/Strings.id.resx +++ b/src/LuaToolsGui/Resources/Strings.id.resx @@ -527,4 +527,9 @@ Ini menghapus file .lua dari Steam\config\stplug-in. Mulai ulang Steam setelahny Kamu sudah mencapai batas harian Hubcap. Tidak ada manifes Hubcap untuk aplikasi ini. Unduhan Hubcap gagal ({0}). + Game + Terbaru + Baru + Belum ada perbaikan yang dirilis baru-baru ini. + Tidak dapat memuat perbaikan terbaru. Periksa koneksi Anda. diff --git a/src/LuaToolsGui/Resources/Strings.it.resx b/src/LuaToolsGui/Resources/Strings.it.resx index 25e0ada..c86f722 100644 --- a/src/LuaToolsGui/Resources/Strings.it.resx +++ b/src/LuaToolsGui/Resources/Strings.it.resx @@ -527,4 +527,9 @@ Questo elimina i file .lua da Steam\config\stplug-in. Riavvia Steam in seguito a Hai raggiunto il limite giornaliero di Hubcap. Nessun manifest Hubcap disponibile per questa app. Download da Hubcap non riuscito ({0}). + Giochi + Recenti + Nuovo + Nessun fix pubblicato di recente. + Impossibile caricare i fix recenti. Controlla la connessione. diff --git a/src/LuaToolsGui/Resources/Strings.ja.resx b/src/LuaToolsGui/Resources/Strings.ja.resx index d33ec9e..55a66be 100644 --- a/src/LuaToolsGui/Resources/Strings.ja.resx +++ b/src/LuaToolsGui/Resources/Strings.ja.resx @@ -527,4 +527,9 @@ Hubcap の 1 日の上限に達しました。 このアプリ用の Hubcap マニフェストはありません。 Hubcap からのダウンロードに失敗しました ({0})。 + ゲーム + 最近 + 新着 + 最近公開された修正はありません。 + 最近の修正を読み込めませんでした。接続を確認してください。 diff --git a/src/LuaToolsGui/Resources/Strings.ko.resx b/src/LuaToolsGui/Resources/Strings.ko.resx index 52d6586..300e709 100644 --- a/src/LuaToolsGui/Resources/Strings.ko.resx +++ b/src/LuaToolsGui/Resources/Strings.ko.resx @@ -527,4 +527,9 @@ 일일 Hubcap 한도에 도달했습니다. 이 앱에 사용할 수 있는 Hubcap 매니페스트가 없습니다. Hubcap 다운로드 실패 ({0}). + 게임 + 최근 + 새 항목 + 최근에 출시된 수정이 없습니다. + 최근 수정을 불러올 수 없습니다. 연결을 확인하세요. diff --git a/src/LuaToolsGui/Resources/Strings.nb.resx b/src/LuaToolsGui/Resources/Strings.nb.resx index 069929f..67dae30 100644 --- a/src/LuaToolsGui/Resources/Strings.nb.resx +++ b/src/LuaToolsGui/Resources/Strings.nb.resx @@ -527,4 +527,9 @@ Dette sletter .lua-filene fra Steam\config\stplug-in. Start Steam på nytt etter Du har nådd den daglige Hubcap-grensen. Det finnes ingen Hubcap-manifest for denne appen. Hubcap-nedlastingen mislyktes ({0}). + Spill + Nylige + Ny + Ingen nylige fikser. + Kunne ikke laste nylige fikser. Sjekk tilkoblingen din. diff --git a/src/LuaToolsGui/Resources/Strings.nl.resx b/src/LuaToolsGui/Resources/Strings.nl.resx index f62ec69..a87fd78 100644 --- a/src/LuaToolsGui/Resources/Strings.nl.resx +++ b/src/LuaToolsGui/Resources/Strings.nl.resx @@ -527,4 +527,9 @@ Dit verwijdert de .lua-bestanden uit Steam\config\stplug-in. Herstart Steam daar Je dagelijkse Hubcap-limiet is bereikt. Er is geen Hubcap-manifest voor deze app. Hubcap-download mislukt ({0}). + Games + Recent + Nieuw + Geen recente fixes. + Kon recente fixes niet laden. Controleer je verbinding. diff --git a/src/LuaToolsGui/Resources/Strings.pl.resx b/src/LuaToolsGui/Resources/Strings.pl.resx index 3d3bfef..9b49cf3 100644 --- a/src/LuaToolsGui/Resources/Strings.pl.resx +++ b/src/LuaToolsGui/Resources/Strings.pl.resx @@ -527,4 +527,9 @@ Spowoduje to usunięcie plików .lua z Steam\config\stplug-in. Następnie urucho Osiągnięto dzienny limit Hubcap. Brak manifestu Hubcap dla tej aplikacji. Pobieranie z Hubcap nie powiodło się ({0}). + Gry + Ostatnie + Nowe + Brak ostatnio wydanych poprawek. + Nie udało się załadować ostatnich poprawek. Sprawdź połączenie. diff --git a/src/LuaToolsGui/Resources/Strings.pt-BR.resx b/src/LuaToolsGui/Resources/Strings.pt-BR.resx index 6d9ba99..3ecdcb7 100644 --- a/src/LuaToolsGui/Resources/Strings.pt-BR.resx +++ b/src/LuaToolsGui/Resources/Strings.pt-BR.resx @@ -527,4 +527,9 @@ Isso exclui os arquivos .lua de Steam\config\stplug-in. Reinicie o Steam depois Você atingiu seu limite diário do Hubcap. Nenhum manifesto do Hubcap disponível para este app. Falha no download do Hubcap ({0}). + Jogos + Recentes + Novo + Nenhuma correção lançada recentemente. + Não foi possível carregar as correções recentes. Verifique sua conexão. diff --git a/src/LuaToolsGui/Resources/Strings.pt-PT.resx b/src/LuaToolsGui/Resources/Strings.pt-PT.resx index b2c0e88..9319011 100644 --- a/src/LuaToolsGui/Resources/Strings.pt-PT.resx +++ b/src/LuaToolsGui/Resources/Strings.pt-PT.resx @@ -527,4 +527,9 @@ Isto elimina os ficheiros .lua de Steam\config\stplug-in. Reinicie o Steam depoi Atingiste o teu limite diário do Hubcap. Nenhum manifesto Hubcap disponível para esta app. Falha no download do Hubcap ({0}). + Jogos + Recentes + Novo + Não há correções lançadas recentemente. + Não foi possível carregar as correções recentes. Verifique a sua ligação. diff --git a/src/LuaToolsGui/Resources/Strings.resx b/src/LuaToolsGui/Resources/Strings.resx index 453cf27..fc925e7 100644 --- a/src/LuaToolsGui/Resources/Strings.resx +++ b/src/LuaToolsGui/Resources/Strings.resx @@ -352,6 +352,11 @@ This deletes the .lua files from Steam\config\stplug-in. Restart Steam afterward Couldn't apply fix Refreshed {0} games with fixes. + Games + Recent + New + No fixes released recently. + Couldn't load recent fixes. Check your connection. Let's get Luing™! diff --git a/src/LuaToolsGui/Resources/Strings.ro.resx b/src/LuaToolsGui/Resources/Strings.ro.resx index a5b93c4..0134bb2 100644 --- a/src/LuaToolsGui/Resources/Strings.ro.resx +++ b/src/LuaToolsGui/Resources/Strings.ro.resx @@ -527,4 +527,9 @@ Aceasta șterge fișierele .lua din Steam\config\stplug-in. Repornește Steam du Ai atins limita zilnică Hubcap. Nu există manifest Hubcap pentru această aplicație. Descărcarea Hubcap a eșuat ({0}). + Jocuri + Recente + Nou + Nicio remediere lansată recent. + Nu s-au putut încărca remedierile recente. Verifică-ți conexiunea. diff --git a/src/LuaToolsGui/Resources/Strings.ru.resx b/src/LuaToolsGui/Resources/Strings.ru.resx index 9c2909d..5b62e65 100644 --- a/src/LuaToolsGui/Resources/Strings.ru.resx +++ b/src/LuaToolsGui/Resources/Strings.ru.resx @@ -527,4 +527,9 @@ Достигнут дневной лимит Hubcap. Для этого приложения нет манифеста Hubcap. Не удалось загрузить с Hubcap ({0}). + Игры + Последние + Новое + Свежих фиксов пока нет. + Не удалось загрузить свежие фиксы. Проверьте подключение. diff --git a/src/LuaToolsGui/Resources/Strings.sv.resx b/src/LuaToolsGui/Resources/Strings.sv.resx index b60dc7d..f941e11 100644 --- a/src/LuaToolsGui/Resources/Strings.sv.resx +++ b/src/LuaToolsGui/Resources/Strings.sv.resx @@ -527,4 +527,9 @@ Detta tar bort .lua-filerna från Steam\config\stplug-in. Starta om Steam efter Du har nått din dagliga Hubcap-gräns. Det finns inget Hubcap-manifest för den här appen. Hubcap-nedladdningen misslyckades ({0}). + Spel + Senaste + Ny + Inga senaste fixar. + Det gick inte att läsa in senaste fixar. Kontrollera din anslutning. diff --git a/src/LuaToolsGui/Resources/Strings.th.resx b/src/LuaToolsGui/Resources/Strings.th.resx index 62e27cd..aa9dd37 100644 --- a/src/LuaToolsGui/Resources/Strings.th.resx +++ b/src/LuaToolsGui/Resources/Strings.th.resx @@ -527,4 +527,9 @@ คุณใช้ Hubcap ครบตามขีดจำกัดรายวันแล้ว ไม่มี manifest ของ Hubcap สำหรับแอปนี้ ดาวน์โหลดจาก Hubcap ไม่สำเร็จ ({0}) + เกม + ล่าสุด + ใหม่ + ยังไม่มีการแก้ไขที่เผยแพร่ล่าสุด + ไม่สามารถโหลดการแก้ไขล่าสุดได้ โปรดตรวจสอบการเชื่อมต่อของคุณ diff --git a/src/LuaToolsGui/Resources/Strings.tr.resx b/src/LuaToolsGui/Resources/Strings.tr.resx index dc12e31..f911bfc 100644 --- a/src/LuaToolsGui/Resources/Strings.tr.resx +++ b/src/LuaToolsGui/Resources/Strings.tr.resx @@ -527,4 +527,9 @@ Bu işlem, .lua dosyalarını Steam\config\stplug-in konumundan siler. Değişik Günlük Hubcap sınırına ulaştın. Bu uygulama için Hubcap manifesti yok. Hubcap indirmesi başarısız ({0}). + Oyunlar + Son + Yeni + Son zamanlarda yayımlanan düzeltme yok. + Son düzeltmeler yüklenemedi. Bağlantınızı kontrol edin. diff --git a/src/LuaToolsGui/Resources/Strings.uk.resx b/src/LuaToolsGui/Resources/Strings.uk.resx index 74fe43c..03960e9 100644 --- a/src/LuaToolsGui/Resources/Strings.uk.resx +++ b/src/LuaToolsGui/Resources/Strings.uk.resx @@ -527,4 +527,9 @@ Досягнуто денний ліміт Hubcap. Для цього застосунку немає маніфесту Hubcap. Не вдалося завантажити з Hubcap ({0}). + Ігри + Останні + Нове + Свіжих фіксів поки немає. + Не вдалося завантажити свіжі фікси. Перевірте з'єднання. diff --git a/src/LuaToolsGui/Resources/Strings.vi.resx b/src/LuaToolsGui/Resources/Strings.vi.resx index 5ddb4cc..a8f1947 100644 --- a/src/LuaToolsGui/Resources/Strings.vi.resx +++ b/src/LuaToolsGui/Resources/Strings.vi.resx @@ -527,4 +527,9 @@ Thao tác này sẽ xóa các tệp .lua khỏi Steam\config\stplug-in. Sau đó Bạn đã đạt giới hạn Hubcap hằng ngày. Không có manifest Hubcap cho ứng dụng này. Tải xuống từ Hubcap thất bại ({0}). + Trò chơi + Mới nhất + Mới + Chưa có bản sửa lỗi nào được phát hành gần đây. + Không thể tải bản sửa lỗi gần đây. Kiểm tra kết nối của bạn. diff --git a/src/LuaToolsGui/Resources/Strings.zh-Hans.resx b/src/LuaToolsGui/Resources/Strings.zh-Hans.resx index d1c6601..c89b67a 100644 --- a/src/LuaToolsGui/Resources/Strings.zh-Hans.resx +++ b/src/LuaToolsGui/Resources/Strings.zh-Hans.resx @@ -547,4 +547,9 @@ 已达到每日 Hubcap 限额。 此应用没有可用的 Hubcap 清单。 Hubcap 下载失败({0})。 + 游戏 + 最近 + + 暂无近期发布的修复。 + 无法加载最近的修复。请检查你的网络连接。 diff --git a/src/LuaToolsGui/Resources/Strings.zh-Hant.resx b/src/LuaToolsGui/Resources/Strings.zh-Hant.resx index d8d3234..20cd6fb 100644 --- a/src/LuaToolsGui/Resources/Strings.zh-Hant.resx +++ b/src/LuaToolsGui/Resources/Strings.zh-Hant.resx @@ -527,4 +527,9 @@ 已達到每日 Hubcap 上限。 此應用程式沒有可用的 Hubcap 資訊清單。 Hubcap 下載失敗({0})。 + 遊戲 + 最近 + + 暫無近期發布的修正。 + 無法載入最近的修正。請檢查你的網路連線。 diff --git a/src/LuaToolsGui/Services/LuaToolsApiClient.cs b/src/LuaToolsGui/Services/LuaToolsApiClient.cs index dc9e31d..2c45c1f 100644 --- a/src/LuaToolsGui/Services/LuaToolsApiClient.cs +++ b/src/LuaToolsGui/Services/LuaToolsApiClient.cs @@ -188,6 +188,35 @@ public Task GenerateDlcAsync( return await ReadJsonAsync(res, ct); } + /// + /// Public: the most recently-published Denuvo fixes across ALL games. There's no /api/denuvo feed + /// endpoint, so this reads the (anon-readable) Supabase `denuvo_fixes` table directly via PostgREST, + /// the same way reads `user_downloads`. Returns the newest + /// fixes, each with its game name/header and tags embedded. Null on failure. + /// + public async Task?> GetRecentDenuvoFixesAsync( + int limit = 25, CancellationToken ct = default) + { + try + { + // PostgREST select with embedded resources (to-one denuvo_games; to-many denuvo_fix_tags, + // each carrying its denuvo_tags). Bounded read; anon RLS permits SELECT on these tables. + string url = $"{AppConfig.SupabaseUrl}/rest/v1/denuvo_fixes" + + "?select=id,appid,title,description,created_at," + + "denuvo_games(name,header_image)," + + "denuvo_fix_tags(tag_id,denuvo_tags(id,name,slug,color))" + + $"&order=created_at.desc&limit={limit}"; + + var req = new HttpRequestMessage(HttpMethod.Get, url); + req.Headers.TryAddWithoutValidation("apikey", AppConfig.SupabaseAnonKey); + + using var res = await _http.SendAsync(req, ct); + if (!res.IsSuccessStatusCode) return null; + return await ReadJsonAsync>(res, ct); + } + catch { return null; } // offline / table locked down → the Recent tab shows its own error state + } + /// /// Auth: download a fix's "manifest" or "fix" slot. The endpoint returns a short-lived signed /// R2 URL (counts toward 25/day); we then fetch the file from that URL. Caller must be signed in. diff --git a/src/LuaToolsGui/ViewModels/FixesViewModel.cs b/src/LuaToolsGui/ViewModels/FixesViewModel.cs index c16be97..3dade0a 100644 --- a/src/LuaToolsGui/ViewModels/FixesViewModel.cs +++ b/src/LuaToolsGui/ViewModels/FixesViewModel.cs @@ -8,6 +8,9 @@ namespace LuaToolsGui.ViewModels; +/// The two sub-tabs on the Fixes page: the game grid (default) and the recently-added feed. +public enum FixesPage { Games, Recent } + /// A game card in the Fixes grid. public partial class FixGameCardVm(DenuvoGameListing g) : ObservableObject { @@ -65,6 +68,47 @@ private static string FormatDate(string? iso) => DateTimeOffset.TryParse(iso, out var d) ? d.UtcDateTime.ToString("d MMM yyyy") : ""; } +/// One entry in the Fixes page's "Recently added" feed (a fix, with its game + tags). +public partial class RecentFixVm(DenuvoRecentFix f) : ObservableObject +{ + public string Id { get; } = f.Id; + public string AppId { get; } = f.AppId; + public string Title { get; } = f.Title; + public string? Description { get; } = f.Description; + public IReadOnlyList Tags { get; } = f.Tags; + + private readonly string? _headerImage = f.Game?.HeaderImage; + private readonly string? _createdAt = f.CreatedAt; + + public string GameNameLabel => + string.IsNullOrWhiteSpace(f.Game?.Name) ? $"App ID: {AppId}" : f.Game!.Name; + public string BuildLabel => + string.Format(Resources.Strings.Fixes_Build, string.IsNullOrWhiteSpace(Title) ? "—" : Title); + public string DateLabel => FormatDate(_createdAt); + public bool IsNew => TryParseDate(_createdAt, out var d) && d >= DateTime.UtcNow.AddDays(-3); + + /// Local cached cover path (set after CoverCache resolves it); bound via ImagePathToSource. + [ObservableProperty] private string? _cover; + private int _resolving; + + public async Task EnsureCoverAsync(CoverCache covers) + { + if (Cover is not null || string.IsNullOrWhiteSpace(_headerImage)) return; + if (!long.TryParse(AppId, out long appid)) return; + if (Interlocked.Exchange(ref _resolving, 1) == 1) return; + try + { + string? local = covers.GetLocalPath(appid) ?? await covers.EnsureAsync(appid, _headerImage!); + if (local is not null) Cover = local; + } + finally { Interlocked.Exchange(ref _resolving, 0); } + } + + private static bool TryParseDate(string? iso, out DateTimeOffset d) => DateTimeOffset.TryParse(iso, out d); + private static string FormatDate(string? iso) => + DateTimeOffset.TryParse(iso, out var d) ? d.UtcDateTime.ToString("d MMM yyyy") : ""; +} + /// /// "Fixes" page: browse games with Denuvo fixes (grid + search + tag filter), open a game to see its /// fixes, and download a fix's manifest (force-locked lua install) or fix zip (extract into the game @@ -104,6 +148,32 @@ public FixesViewModel( public ObservableCollection Tags { get; } = []; + // ── Sub-tabs: game grid (default) vs the recently-added fixes feed ── + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(IsGamesMode))] + [NotifyPropertyChangedFor(nameof(IsRecentMode))] + private FixesPage _page = FixesPage.Games; + + public bool IsGamesMode => Page == FixesPage.Games; + public bool IsRecentMode => Page == FixesPage.Recent; + + [RelayCommand] + private void ShowGames() => Page = FixesPage.Games; + + [RelayCommand] + private void ShowRecent() + { + Page = FixesPage.Recent; + _ = LoadRecentAsync(); // usually a no-op: LoadAsync warms the feed at page load + } + + public ObservableCollection RecentFixes { get; } = []; + [ObservableProperty] private bool _isLoadingRecent; + [ObservableProperty] private string? _recentEmptyMessage; + + /// True once the "Recent" feed has at least one entry (gates the feed vs its empty/error message). + public bool HasRecentItems => RecentFixes.Count > 0; + // IsLoading, EmptyMessage and the IsEmpty gating are inherited from PagedListViewModel. // Page size persists via SavePageSizeSetting below. protected override void SavePageSizeSetting(int size) => settings.FixesPageSize = size; @@ -166,6 +236,9 @@ public async Task LoadAsync(bool force = false) foreach (var t in data.Tags) Tags.Add(new TagPillVm(t)); ApplyFilter(); if (_allGames.Count == 0) EmptyMessage = Resources.Strings.Fixes_Empty_None; + + // Warm the "Recent" sub-tab in the background (one bounded PostgREST read, no auth). + _ = LoadRecentAsync(); } catch { @@ -177,12 +250,48 @@ public async Task LoadAsync(bool force = false) } } + /// Fetch the most recently-published fixes (feed for the "Recent" sub-tab). Loads once per + /// session unless (the Refresh button) re-fetches. + public async Task LoadRecentAsync(bool force = false) + { + if (!force && RecentFixes.Count > 0) return; + IsLoadingRecent = true; + try + { + var fixes = await api.GetRecentDenuvoFixesAsync(limit: 25); + if (fixes is null) + { + RecentEmptyMessage = Resources.Strings.Fixes_Recent_Err_Load; + return; + } + + RecentFixes.Clear(); + foreach (var f in fixes) RecentFixes.Add(new RecentFixVm(f)); + foreach (var f in RecentFixes) _ = f.EnsureCoverAsync(covers); + RecentEmptyMessage = RecentFixes.Count == 0 ? Resources.Strings.Fixes_Recent_Empty : null; + OnPropertyChanged(nameof(HasRecentItems)); + } + catch + { + RecentEmptyMessage = Resources.Strings.Fixes_Recent_Err_Load; + } + finally + { + IsLoadingRecent = false; + } + } + + [RelayCommand] + private Task OpenRecentFix(RecentFixVm fix) => + long.TryParse(fix.AppId, out long appId) ? OpenForAppIdAsync(appId) : Task.CompletedTask; + [RelayCommand] private Task Refresh() => RefreshWithCooldownAsync(async () => { if (SearchText.Length > 0) SearchText = ""; // reset filter → full list visible if (SelectedTagId is not null) SelectTag(SelectedTagId); // clear active tag (toggles off) await LoadAsync(force: true); + await LoadRecentAsync(force: true); toast.Show(Resources.Strings.Fixes_Toast_Refreshed_Title, string.Format(Resources.Strings.Fixes_Toast_Refreshed_Body, _allGames.Count)); }); diff --git a/src/LuaToolsGui/Views/FixesView.xaml b/src/LuaToolsGui/Views/FixesView.xaml index f00ad3f..09a661e 100644 --- a/src/LuaToolsGui/Views/FixesView.xaml +++ b/src/LuaToolsGui/Views/FixesView.xaml @@ -26,6 +26,7 @@ + @@ -47,16 +48,82 @@ Icon="{ui:SymbolIcon ArrowSync24}" /> + + + + + + + + + Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" + Visibility="{Binding IsGamesMode, Converter={StaticResource BoolToVis}}" /> - + @@ -103,9 +170,14 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Grid.Row="5" + Margin="0,12,0,2"> + + +