Compare commits

...

11 Commits

Author SHA1 Message Date
mqudsi
572ad1eac5 Exclude time spent with emulator paused from play time (ryubing/ryujinx!55)
See merge request ryubing/ryujinx!55
2025-06-19 16:33:10 -05:00
Coxxs
6bb2af0091 Implement CreateLibraryAppletEx in ILibraryAppletCreator (ryubing/ryujinx!69)
See merge request ryubing/ryujinx!69
2025-06-19 15:48:06 -05:00
WilliamWsyHK
534a194ed9 Correct typo on part of the character for word "server" (ryubing/ryujinx!68)
See merge request ryubing/ryujinx!68
2025-06-19 15:25:40 -05:00
GreemDev
331805791e infra: [ci skip] fix inconsistent namespaces from update library 2025-06-19 04:26:22 -05:00
GreemDev
6773406bb6 infra: Use Ryujinx.UpdateClient NuGet package for checking for updates.
Main benefit to this is sharing the C# model definitions from what the server returns and Ryujinx uses in-app without differences.
Additionally removed the GitHub API JSON models.
2025-06-19 04:18:33 -05:00
GreemDev
6226eadf55 docs: compat: The Legend of Nayuta: Boundless Trails: ingame (ryubing/ryujinx!59) 2025-06-18 14:31:08 -05:00
yeager
b1cde5fd97 Updated Swedish translation (ryubing/ryujinx!66)
See merge request ryubing/ryujinx!66
2025-06-17 13:05:39 -05:00
Hack茶ん
39944b2063 Update Korean translation (ryubing/ryujinx!64)
See merge request ryubing/ryujinx!64
2025-06-17 03:21:30 -05:00
GreemDev
973c6ba5df UI: RPC: Squeakross: Home Squeak Home image
docs: compat: Squeakross: Home Squeak Home: Playable
2025-06-16 02:06:45 -05:00
GreemDev
6803c91da8 infra: Add package source mappings for Ryujinx.UpdateClient to silence compile warnings 2025-06-16 02:05:11 -05:00
GreemDev
557c2a50b2 infra: Add NuGet config to solution items 2025-06-16 02:04:48 -05:00
16 changed files with 93 additions and 127 deletions

View File

@@ -42,6 +42,8 @@
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.20.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.29" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.29" />
<PackageVersion Include="Gommon" Version="2.7.1.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.6.0" />

View File

@@ -77,6 +77,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Gene
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
@@ -84,10 +86,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props
.github\workflows\release.yml = .github\workflows\release.yml
nuget.config = nuget.config
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

View File

@@ -2089,7 +2089,7 @@
"pl_PL": "Całkowity czas gry: {0}",
"pt_BR": "Tempo total de jogo: {0}",
"ru_RU": "",
"sv_SE": "",
"sv_SE": "Total speltid: {0}",
"th_TH": "",
"tr_TR": "Toplam Oyun Süresi: {0}",
"uk_UA": "",
@@ -4009,7 +4009,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "Ryujinx 1.1.1403을 연상시키는 이전 Avalonia Ryujinx UI를 표시합니다. 이 기능은 Windows가 아닌 플랫폼에서는 기본적으로 활성화됩니다.\n 클래식 스타일의 타이틀 바가 돌아왔고 주요 창 레이아웃 재작업이 역전되었습니다. 이 툴팁 위의 설정 탐색 배치와 같은 작업입니다.",
"ko_KR": "Ryujinx 1.1.1403을 연상시키는 이전 Avalonia Ryujinx UI를 표시합니다. 이 기능은 윈도가 아닌 플랫폼에서는 기본적으로 활성화됩니다.\n 클래식 스타일의 타이틀 바가 돌아왔고 주요 창 레이아웃 변경 사항이 원래대로 적용됩니다. 이 툴팁 위의 설정 탐색 배치와 같은 경우입니다.",
"no_NO": "Vis det eldre Avalonia Ryujinx-grensesnittet som minner om Ryujinx 1.1.1403. Dette er aktivert som standard på plattformer som ikke er Windows.\nTittellinjen i klassisk stil er tilbake, og store omarbeidinger av vindusoppsettet er reversert, for eksempel plasseringen av innstillingsnavigasjonen over dette verktøytipset.",
"pl_PL": "",
"pt_BR": "Mostrar a Interface Avalonia antiga do Ryujinx 1.1.1403. Esta versão é ativada por padrão nas plataformas que não sejam Windows. \nO estilo clássico da Barra de Título retorna e grande parte das mudanças do Layout de janela são revertidas; assim como as configurações de posicionamento da navegação acima dessa descrição.",
@@ -7214,7 +7214,7 @@
"pl_PL": "",
"pt_BR": "Configuração encontrada:\n\nNome:\t{0}\nGUID:\t{1}\n\n Aguardando conexão do controle...",
"ru_RU": "",
"sv_SE": "",
"sv_SE": "Konfiguration hittad:\n\nNamn:\t{0}\nGUID:\t{1}\n\n Väntar på anslutning till kontroller...",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -13139,12 +13139,12 @@
"pl_PL": "",
"pt_BR": "Falha em atualizar a versão do Ryujinx recebida do servidor de atualização.",
"ru_RU": "",
"sv_SE": "",
"sv_SE": "Det gick inte att konvertera Ryujinx-versionen som mottogs från uppdateringsservern.",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "无法转换从更新服务器接收的 Ryujinx 版本。",
"zh_TW": "無法轉換從更新服器接收的 Ryujinx 版本。"
"zh_TW": "無法轉換從更新服器接收的 Ryujinx 版本。"
}
},
{
@@ -16564,7 +16564,7 @@
"pl_PL": "",
"pt_BR": "Se esta opção está ativada nas configurações customizadas, as configurações globais de entrada serão usadas.\n\nNas configurações globais: você pode ativar ou desativá-las se necessário; está configuração será herdada por qualquer nova configuração customizada criada.",
"ru_RU": "Если эта опция включена в пользовательских настройках, будет использована глобальная конфигурация ввода.\n\nВ глобальных настройках: переключите эту опцию по своему усмотрению, это будет унаследовано для вновь созданых пользовательских конфигураций",
"sv_SE": "",
"sv_SE": "Om det här alternativet är aktiverat i anpassade inställningar kommer den globala inmatningskonfigurationen att användas.\n\nI de globala inställningarna: du kan aktivera eller inaktivera det efter behov; den här inställningen kommer att ärvas av alla nya anpassade konfigurationer som skapas.",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -23439,7 +23439,7 @@
"pl_PL": "",
"pt_BR": "Ver Registro",
"ru_RU": "",
"sv_SE": "",
"sv_SE": "Visa ändringslogg",
"th_TH": "ด",
"tr_TR": "",
"uk_UA": "",
@@ -23669,7 +23669,7 @@
"tr_TR": "",
"uk_UA": "Вимкнути хостинг P2P мережі, піри будуть підключатися через майстер-сервер замість прямого з'єднання з вами.",
"zh_CN": "禁用 P2P 网络连接,对方将通过主服务器进行连接,而不是直接连接到您。",
"zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理服器而非直接連線至你的主機。"
"zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理服器而非直接連線至你的主機。"
}
},
{
@@ -24539,7 +24539,7 @@
"pl_PL": "Gry i Aplikacje",
"pt_BR": "Jogos e Aplicativos",
"ru_RU": "Игры и Приложения",
"sv_SE": "Spel och Applikationer",
"sv_SE": "Spel och applikationer",
"th_TH": "",
"tr_TR": "Oyunlar ve Uygulamalar",
"uk_UA": "Ігри та Додатки",
@@ -24589,7 +24589,7 @@
"pl_PL": "Problemy i Cechy",
"pt_BR": "Problemas e Características",
"ru_RU": "Проблемы и Особенности",
"sv_SE": "Problem och Egenskaper",
"sv_SE": "Problem och egenskaper",
"th_TH": "",
"tr_TR": "Sorunlar ve Özellikler",
"uk_UA": "Проблеми та Особливості",

View File

@@ -2746,6 +2746,7 @@
01005D701264A000,"SpyHack",,playable,2021-04-15 10:53:51
010077B00E046000,"Spyro™ Reignited Trilogy",nvdec;UE4,playable,2022-09-11 18:38:33
0100085012A0E000,"Squeakers",,playable,2020-12-13 12:13:05
0100E1D01EB2E000,"Squeakross: Home Squeak Home",,playable,2025-06-16 02:02:00
010009300D31C000,"Squidgies Takeover",,playable,2020-07-20 22:28:08
0100FCD0102EC000,"Squidlit",,playable,2020-08-06 12:38:32
0100EBF00E702000,"STAR OCEAN First Departure R",nvdec,playable,2021-07-05 19:29:16
@@ -3016,6 +3017,7 @@
01009B101044C000,"The Legend of Heroes: Trails of Cold Steel III Demo",demo;nvdec,playable,2021-04-23 01:07:32
0100D3C010DE8000,"The Legend of Heroes: Trails of Cold Steel IV",nvdec,playable,2021-04-23 14:01:05
01005E5013862000,"THE LEGEND OF HEROES: ZERO NO KISEKI KAI [英雄傳說 零之軌跡:改]",crash,nothing,2021-09-30 14:41:07
01009C901ACEE000,"The Legend of Nayuta: Boundless Trails",,ingame,2025-06-12 15:47
01008CF01BAAC000,"The Legend of Zelda Echoes of Wisdom",nvdec;ASTC;intel-vendor-bug,playable,2024-10-01 14:11:01
0100509005AF2000,"The Legend of Zelda: Breath of the Wild Demo",demo,ingame,2022-12-24 05:02:58
01007EF00011E000,"The Legend of Zelda™: Breath of the Wild",gpu;amd-vendor-bug;mac-bug,ingame,2024-09-23 19:35:46
1 title_id game_name labels status last_updated
2746 01005D701264A000 SpyHack playable 2021-04-15 10:53:51
2747 010077B00E046000 Spyro™ Reignited Trilogy nvdec;UE4 playable 2022-09-11 18:38:33
2748 0100085012A0E000 Squeakers playable 2020-12-13 12:13:05
2749 0100E1D01EB2E000 Squeakross: Home Squeak Home playable 2025-06-16 02:02:00
2750 010009300D31C000 Squidgies Takeover playable 2020-07-20 22:28:08
2751 0100FCD0102EC000 Squidlit playable 2020-08-06 12:38:32
2752 0100EBF00E702000 STAR OCEAN First Departure R nvdec playable 2021-07-05 19:29:16
3017 01009B101044C000 The Legend of Heroes: Trails of Cold Steel III Demo demo;nvdec playable 2021-04-23 01:07:32
3018 0100D3C010DE8000 The Legend of Heroes: Trails of Cold Steel IV nvdec playable 2021-04-23 14:01:05
3019 01005E5013862000 THE LEGEND OF HEROES: ZERO NO KISEKI KAI [英雄傳說 零之軌跡:改] crash nothing 2021-09-30 14:41:07
3020 01009C901ACEE000 The Legend of Nayuta: Boundless Trails ingame 2025-06-12 15:47
3021 01008CF01BAAC000 The Legend of Zelda Echoes of Wisdom nvdec;ASTC;intel-vendor-bug playable 2024-10-01 14:11:01
3022 0100509005AF2000 The Legend of Zelda: Breath of the Wild Demo demo ingame 2022-12-24 05:02:58
3023 01007EF00011E000 The Legend of Zelda™: Breath of the Wild gpu;amd-vendor-bug;mac-bug ingame 2024-09-23 19:35:46

View File

@@ -8,4 +8,18 @@
<!--<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />-->
<add key="Ryujinx.UpdateClient" value="https://git.ryujinx.app/api/v4/projects/71/packages/nuget/index.json" />
</packageSources>
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="Ryujinx.UpdateClient">
<package pattern="Ryujinx.UpdateClient" />
<package pattern="Ryujinx.Systems.Update.Common" />
</packageSource>
<!--<packageSource key="LibHacAlpha">
<package pattern="Ryujinx.LibHac" />
</packageSource>-->
</packageSourceMapping>
</configuration>

View File

@@ -195,6 +195,7 @@ namespace Ryujinx.Common
"01008d100d43e000", // Saints Row IV
"0100de600beee000", // Saints Row: The Third - The Full Package
"01001180021fa000", // Shovel Knight: Specter of Torment
"0100e1D01eb2e000", // Squeakross: Home Squeak Home
"0100e65002bb8000", // Stardew Valley
"0100d7a01b7a2000", // Star Wars: Bounty Hunter
"0100800015926000", // Suika Game

View File

@@ -21,6 +21,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success;
}
[CommandCmif(3)] // 20.0.0+
// CreateLibraryAppletEx(u32, u32, u64) -> object<nn::am::service::ILibraryAppletAccessor>
public ResultCode CreateLibraryAppletEx(ServiceCtx context)
{
AppletId appletId = (AppletId)context.RequestData.ReadInt32();
_ = context.RequestData.ReadInt32(); // libraryAppletMode
_ = context.RequestData.ReadUInt64(); // threadId
MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System));
return ResultCode.Success;
}
[CommandCmif(10)]
// CreateStorage(u64) -> object<nn::am::service::IStorage>
public ResultCode CreateStorage(ServiceCtx context)

View File

@@ -1,9 +0,0 @@
namespace Ryujinx.Ava.Common.Models.Github
{
public class GithubReleaseAssetJsonResponse
{
public string Name { get; set; }
public string State { get; set; }
public string BrowserDownloadUrl { get; set; }
}
}

View File

@@ -1,12 +0,0 @@
using System.Collections.Generic;
namespace Ryujinx.Ava.Common.Models.Github
{
public class GithubReleasesJsonResponse
{
public string Name { get; set; }
public string TagName { get; set; }
public List<GithubReleaseAssetJsonResponse> Assets { get; set; }
}
}

View File

@@ -1,7 +0,0 @@
using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Common.Models.Github
{
[JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext;
}

View File

@@ -65,6 +65,8 @@
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" />
<PackageReference Include="Ryujinx.UpdateClient" />
<PackageReference Include="Ryujinx.Systems.Update.Common" />
<PackageReference Include="securifybv.ShellLink" />
<PackageReference Include="Sep" />
<PackageReference Include="Silk.NET.Vulkan" />

View File

@@ -75,6 +75,7 @@ namespace Ryujinx.Ava.Systems
private readonly long _ticksPerFrame;
private readonly Stopwatch _chrono;
private readonly Stopwatch _playTimer;
private long _ticks;
private readonly AccountManager _accountManager;
@@ -175,6 +176,7 @@ namespace Ryujinx.Ava.Systems
_chrono = new Stopwatch();
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
_playTimer = new Stopwatch();
if (ApplicationPath.StartsWith("@SystemContent"))
{
@@ -565,6 +567,7 @@ namespace Ryujinx.Ava.Systems
public void Stop()
{
_isActive = false;
_playTimer.Stop();
}
private void Exit()
@@ -616,7 +619,7 @@ namespace Ryujinx.Ava.Systems
private void Dispose()
{
if (Device.Processes != null)
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText, _playTimer.Elapsed);
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
@@ -635,6 +638,7 @@ namespace Ryujinx.Ava.Systems
_gpuCancellationTokenSource.Dispose();
_chrono.Stop();
_playTimer.Stop();
}
public void DisposeGpu()
@@ -868,6 +872,7 @@ namespace Ryujinx.Ava.Systems
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
appMetadata => appMetadata.UpdatePreGame()
);
_playTimer.Start();
return true;
}
@@ -877,6 +882,7 @@ namespace Ryujinx.Ava.Systems
Device?.System.TogglePauseEmulation(false);
_viewModel.IsPaused = false;
_playTimer.Start();
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
}
@@ -886,6 +892,7 @@ namespace Ryujinx.Ava.Systems
Device?.System.TogglePauseEmulation(true);
_viewModel.IsPaused = true;
_playTimer.Stop();
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
}

View File

@@ -33,19 +33,11 @@ namespace Ryujinx.Ava.Systems.AppLibrary
/// <summary>
/// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends.
/// </summary>
public void UpdatePostGame()
/// <param name="playTime">The active gameplay time this past session.</param>
public void UpdatePostGame(TimeSpan playTime)
{
DateTime? prevLastPlayed = LastPlayed;
UpdatePreGame();
if (!prevLastPlayed.HasValue)
{
return;
}
TimeSpan diff = DateTime.UtcNow - prevLastPlayed.Value;
double newTotalSeconds = TimePlayed.Add(diff).TotalSeconds;
TimePlayed = TimeSpan.FromSeconds(Math.Round(newTotalSeconds, MidpointRounding.AwayFromZero));
TimePlayed += playTime;
}
}
}

View File

@@ -4,42 +4,26 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
using Ryujinx.Systems.Update.Client;
using Ryujinx.Systems.Update.Common;
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Runtime.InteropServices;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Systems
{
internal static partial class Updater
{
private static string CreateUpdateQueryUrl()
{
#pragma warning disable CS8524
var os = RunningPlatform.CurrentOS switch
#pragma warning restore CS8524
{
OperatingSystemType.MacOS => "mac",
OperatingSystemType.Linux => "linux",
OperatingSystemType.Windows => "win"
};
private static VersionResponse _versionResponse;
var arch = RunningPlatform.Architecture switch
{
Architecture.Arm64 => "arm",
Architecture.X64 => "amd64",
_ => null
};
if (arch is null)
return null;
var rc = ReleaseInformation.IsCanaryBuild ? "canary" : "stable";
return $"https://update.ryujinx.app/latest/query?os={os}&arch={arch}&rc={rc}";
}
private static UpdateClient CreateUpdateClient()
=> UpdateClient.Builder()
.WithServerEndpoint("https://update.ryujinx.app") // This is the default, and doesn't need to be provided; it's here for transparency.
.WithLogger((format, args, caller) =>
Logger.Info?.Print(
LogClass.Application,
args.Length is 0 ? format : format.Format(args),
caller: caller)
);
public static async Task<Optional<(Version Current, Version Incoming)>> CheckVersionAsync(bool showVersionUpToDate = false)
{
@@ -57,39 +41,31 @@ namespace Ryujinx.Ava.Systems
return default;
}
if (CreateUpdateQueryUrl() is not {} updateUrl)
{
Logger.Error?.Print(LogClass.Application, "Could not determine URL for updates.");
_running = false;
return default;
}
Logger.Info?.Print(LogClass.Application, $"Checking for updates from {updateUrl}.");
// Get latest version number from update.ryujinx.app API
using HttpClient jsonClient = ConstructHttpClient();
using UpdateClient updateClient = CreateUpdateClient();
try
{
UpdaterResponse response =
await jsonClient.GetFromJsonAsync(updateUrl, UpdaterResponseJsonContext.Default.UpdaterResponse);
_buildVer = response.Tag;
_buildUrl = response.DownloadUrl;
_changelogUrlFormat = response.ReleaseUrlFormat;
_versionResponse = await updateClient.QueryLatestAsync(ReleaseInformation.IsCanaryBuild
? ReleaseChannel.Canary
: ReleaseChannel.Stable);
}
catch (Exception e)
{
Logger.Error?.Print(LogClass.Application, $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
Logger.Error?.Print(LogClass.Application, $"An error occurred when requesting for updates ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
_running = false;
return default;
}
if (_versionResponse == null)
{
// logging is done via the UpdateClient library
_running = false;
return default;
}
// If build URL not found, assume no new update is available.
if (_buildUrl is null or "")
if (_versionResponse.ArtifactUrl is null or "")
{
if (showVersionUpToDate)
{
@@ -99,7 +75,7 @@ namespace Ryujinx.Ava.Systems
if (userResult is UserResult.Ok)
{
OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion));
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion));
}
}
@@ -111,7 +87,7 @@ namespace Ryujinx.Ava.Systems
}
if (!Version.TryParse(_buildVer, out Version newVersion))
if (!Version.TryParse(_versionResponse.Version, out Version newVersion))
{
Logger.Error?.Print(LogClass.Application,
$"Failed to convert the received {RyujinxApp.FullAppName} version from the update server!");
@@ -127,17 +103,5 @@ namespace Ryujinx.Ava.Systems
return (currentVersion, newVersion);
}
[JsonSerializable(typeof(UpdaterResponse))]
partial class UpdaterResponseJsonContext : JsonSerializerContext;
public class UpdaterResponse
{
[JsonPropertyName("tag")] public string Tag { get; set; }
[JsonPropertyName("download_url")] public string DownloadUrl { get; set; }
[JsonPropertyName("web_url")] public string ReleaseUrl { get; set; }
[JsonIgnore] public string ReleaseUrlFormat => ReleaseUrl.Replace(Tag, "{0}");
}
}
}

View File

@@ -5,13 +5,11 @@ using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models.Github;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -35,17 +33,13 @@ namespace Ryujinx.Ava.Systems
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
private const int ConnectionCount = 4;
private static string _buildVer;
private static string _buildUrl;
private static long _buildSize;
private static bool _updateSuccessful;
private static bool _running;
private static readonly string[] _windowsDependencyDirs = [];
private static string _changelogUrlFormat = null;
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
{
if (_running)
@@ -72,7 +66,7 @@ namespace Ryujinx.Ava.Systems
if (userResult is UserResult.Ok)
{
OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion));
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion));
}
}
@@ -92,7 +86,7 @@ namespace Ryujinx.Ava.Systems
// GitLab instance is located in Ukraine. Connection times will vary across the world.
buildSizeClient.Timeout = TimeSpan.FromSeconds(10);
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_versionResponse.ArtifactUrl), HttpCompletionOption.ResponseHeadersRead);
_buildSize = message.Content.Headers.ContentRange.Length.Value;
}
@@ -122,7 +116,7 @@ namespace Ryujinx.Ava.Systems
switch (shouldUpdate)
{
case UserResult.Yes:
await UpdateRyujinx(_buildUrl);
await UpdateRyujinx(_versionResponse.ArtifactUrl);
break;
// Secondary button maps to no, which in this case is the show changelog button.
case UserResult.No:

View File

@@ -1688,8 +1688,8 @@ namespace Ryujinx.Ava.UI.ViewModels
RendererHostControl.Focus();
});
public static void UpdateGameMetadata(string titleId)
=> ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame());
public static void UpdateGameMetadata(string titleId, TimeSpan playTime)
=> ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame(playTime));
public void RefreshFirmwareStatus()
{