Skip to content

Commit

Permalink
Temporary Poster Background (#609)
Browse files Browse the repository at this point in the history
# Main Goal
Use poster as temporary background when requested background is not yet
downloaded.
New background retrieval mechanism:
1. Check if background is downloaded
2. If it's downloaded, then load the downloaded background
3. If not yet downloaded, load either last available regional background
or use poster as background instead

Due to the poster having slight transparency, the switching looks a wee
bit janky

This PR also contains IOException fixes especially for background
loading and image cache processing (really noticeable when user uses
Waifu2X)

## PR Status :
- Overall Status : Done
- Commits : Done
- Synced to base (Collapse:main) : Yes
- Build status : OK
- Crashing : No
- Bug found caused by PR : 0
  • Loading branch information
bagusnl authored Nov 24, 2024
2 parents 908c488 + c03a012 commit 7ef4fab
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 22 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 13 additions & 15 deletions CollapseLauncher/Classes/Helper/Image/ImageLoaderHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -288,8 +287,8 @@ private static async Task<FileStream> GenerateCachedStream(FileInfo InputFileInf
{
InputFileInfo.MoveTo(InputFileInfo.FullName + "_old", true);
FileInfo newCachedFileInfo = new FileInfo(InputFileName);
await using (FileStream newCachedFileStream = newCachedFileInfo.Open(StreamUtility.FileStreamCreateWriteOpt))
await using (FileStream oldInputFileStream = InputFileInfo.Open(StreamUtility.FileStreamOpenReadOpt))
await using (FileStream newCachedFileStream = newCachedFileInfo.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
await using (FileStream oldInputFileStream = InputFileInfo.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
await ResizeImageStream(oldInputFileStream, newCachedFileStream, ToWidth, ToHeight);

InputFileInfo.Delete();
Expand Down Expand Up @@ -382,17 +381,16 @@ public static Bitmap Stream2Bitmap(IRandomAccessStream image)
return new Bitmap(image.AsStream()!);
}

public static async ValueTask DownloadAndEnsureCompleteness(string url, string outputPath, bool checkIsHashable, CancellationToken token)
/// <summary>
/// Check if background image is downloaded
/// </summary>
/// <param name="fileInfo">FileInfo of the image to store</param>
/// <param name="checkIsHashable">Is it hashed?</param>
/// <returns>true if downloaded, false if not</returns>
public static ValueTask<bool> DownloadAndEnsureCompleteness(FileInfo fileInfo, bool checkIsHashable)
{
// Initialize the FileInfo and check if the file exist
FileInfo fileInfo = new FileInfo(outputPath);
bool isFileExist = IsFileCompletelyDownloaded(fileInfo, checkIsHashable);

// If the file and the file assumed to exist, then return
if (isFileExist) return;

// If not, then try download the file
await TryDownloadToCompleteness(url, fileInfo, token);
// Check if the file exist
return ValueTask.FromResult(IsFileCompletelyDownloaded(fileInfo, checkIsHashable));
}

public static bool IsFileCompletelyDownloaded(FileInfo fileInfo, bool checkIsHashable)
Expand Down Expand Up @@ -439,7 +437,7 @@ public static bool IsFileCompletelyDownloaded(FileInfo fileInfo, bool checkIsHas
}

#nullable enable
private static bool TryGetMd5HashFromFilename([NotNull] string fileName, out byte[]? hash)
private static bool TryGetMd5HashFromFilename(string fileName, out byte[]? hash)
{
// Set default value for out
hash = null;
Expand Down Expand Up @@ -500,7 +498,7 @@ public static async ValueTask TryDownloadToCompleteness(string url, FileInfo fil
_processingUrls.Add(url);
// Initialize file temporary name
FileInfo fileInfoTemp = new FileInfo(fileInfo.FullName + "_temp");
long fileLength = 0;
long fileLength;

Logger.LogWriteLine($"Start downloading resource from: {url}", LogType.Default, true);

Expand Down
58 changes: 57 additions & 1 deletion CollapseLauncher/Classes/RegionManagement/RegionManagement.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CollapseLauncher.Extension;
using CollapseLauncher.Helper.Background;
using CollapseLauncher.Helper.Image;
using CollapseLauncher.Helper.Loading;
using CollapseLauncher.Helper.Metadata;
Expand Down Expand Up @@ -165,8 +166,63 @@ private async Task DownloadBackgroundImage(CancellationToken Token)
if (!Directory.Exists(backgroundFolder))
Directory.CreateDirectory(backgroundFolder);

var imgFileInfo =
new FileInfo(LauncherMetadataHelper.CurrentMetadataConfig.GameLauncherApi.GameBackgroundImgLocal);

// Start downloading the background image
await ImageLoaderHelper.DownloadAndEnsureCompleteness(LauncherMetadataHelper.CurrentMetadataConfig.GameLauncherApi.GameBackgroundImg, LauncherMetadataHelper.CurrentMetadataConfig.GameLauncherApi.GameBackgroundImgLocal, true, Token);
var isDownloaded = await ImageLoaderHelper.DownloadAndEnsureCompleteness(imgFileInfo, true);

if (isDownloaded)
{
BackgroundImgChanger.ChangeBackground(imgFileInfo.FullName, () =>
{
IsFirstStartup = false;
ColorPaletteUtility.ReloadPageTheme(this, CurrentAppTheme);
}, false, false, true);
return;
}

#nullable enable
string? tempImage = null;
var lastBgCfg = "lastBg-" + LauncherMetadataHelper.CurrentMetadataConfig.GameLauncherApi.GameName +
"-" + LauncherMetadataHelper.CurrentMetadataConfig.GameLauncherApi.GameRegion;

// Check if the last background image exist, then use that temporarily instead
var lastGameBackground = GetAppConfigValue(lastBgCfg).ToString();
if (!string.IsNullOrEmpty(lastGameBackground))
{
if (File.Exists(lastGameBackground))
{
tempImage = lastGameBackground;
}
}

// If the file is not downloaded, use template image first, then download the image
var currentGameType = GamePropertyVault.GetCurrentGameProperty()._GameVersion.GameType;
tempImage ??= currentGameType switch
{
GameNameType.Honkai => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_honkai.png"),
GameNameType.Genshin => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_genshin.png"),
GameNameType.StarRail => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_starrail.png"),
GameNameType.Zenless => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_zzz.png"),
_ => AppDefaultBG
};
BackgroundImgChanger.ChangeBackground(tempImage, () =>
{
IsFirstStartup = false;
ColorPaletteUtility.ReloadPageTheme(this, CurrentAppTheme);
}, false, false, true);
await ImageLoaderHelper.TryDownloadToCompleteness(
LauncherMetadataHelper.CurrentMetadataConfig.GameLauncherApi.GameBackgroundImg,
imgFileInfo,
Token);
BackgroundImgChanger.ChangeBackground(imgFileInfo.FullName, () =>
{
IsFirstStartup = false;
ColorPaletteUtility.ReloadPageTheme(this, CurrentAppTheme);
}, false, true, true);
SetAndSaveConfigValue(lastBgCfg, imgFileInfo.FullName);
#nullable disable
}

private async ValueTask FinalizeLoadRegion(string gameName, string gameRegion)
Expand Down
24 changes: 19 additions & 5 deletions CollapseLauncher/XAMLs/MainApp/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -463,15 +463,23 @@ private void BackgroundImg_IsImageHideEvent(object sender, bool e)
else CurrentBackgroundHandler?.Undimm();
}

private HashSet<string> _processingBackground = new();
private async void CustomBackgroundChanger_Event(object sender, BackgroundImgProperty e)
{
if (_processingBackground.Contains(e.ImgPath))
{
LogWriteLine($"Background {e.ImgPath} is already being processed!", LogType.Warning, true);
return;
}

try
{
_processingBackground.Add(e.ImgPath);
var gameLauncherApi = LauncherMetadataHelper.CurrentMetadataConfig?.GameLauncherApi;
if (gameLauncherApi != null)
{
gameLauncherApi.GameBackgroundImgLocal = e.ImgPath;
IsCustomBG = e.IsCustom;
IsCustomBG = e.IsCustom;

// if (e.IsCustom)
// SetAndSaveConfigValue("CustomBGPath",
Expand All @@ -488,13 +496,14 @@ private async void CustomBackgroundChanger_Event(object sender, BackgroundImgPro
{
case BackgroundMediaUtility.MediaType.Media:
BackgroundNewMediaPlayerGrid.Visibility = Visibility.Visible;
BackgroundNewBackGrid.Visibility = Visibility.Collapsed;
BackgroundNewBackGrid.Visibility = Visibility.Collapsed;
break;
case BackgroundMediaUtility.MediaType.StillImage:
FileStream imgStream = await ImageLoaderHelper.LoadImage(gameLauncherApi.GameBackgroundImgLocal);
FileStream imgStream =
await ImageLoaderHelper.LoadImage(gameLauncherApi.GameBackgroundImgLocal);
BackgroundMediaUtility.SetAlternativeFileStream(imgStream);
BackgroundNewMediaPlayerGrid.Visibility = Visibility.Collapsed;
BackgroundNewBackGrid.Visibility = Visibility.Visible;
BackgroundNewBackGrid.Visibility = Visibility.Visible;
break;
case BackgroundMediaUtility.MediaType.Unknown:
default:
Expand All @@ -505,7 +514,8 @@ private async void CustomBackgroundChanger_Event(object sender, BackgroundImgPro
CurrentBackgroundHandler?.LoadBackground(gameLauncherApi.GameBackgroundImgLocal, e.IsRequestInit,
e.IsForceRecreateCache, ex =>
{
gameLauncherApi.GameBackgroundImgLocal = AppDefaultBG;
gameLauncherApi.GameBackgroundImgLocal =
AppDefaultBG;
LogWriteLine($"An error occured while loading background {e.ImgPath}\r\n{ex}",
LogType.Error, true);
ErrorSender.SendException(ex);
Expand All @@ -518,6 +528,10 @@ private async void CustomBackgroundChanger_Event(object sender, BackgroundImgPro
LogType.Error, true);
ErrorSender.SendException(new Exception($"An error occured while loading background {e.ImgPath}", ex));
}
finally
{
_processingBackground.Remove(e.ImgPath);
}
}

internal async void ChangeBackgroundImageAsRegionAsync(bool ShowLoadingMsg = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using static CollapseLauncher.InnerLauncherConfig;
using static CollapseLauncher.Pages.OOBE.OOBESelectGameBGProp;
using static Hi3Helper.Logger;
using static Hi3Helper.Shared.Region.LauncherConfig;

namespace CollapseLauncher.Pages.OOBE
{
Expand Down Expand Up @@ -90,9 +91,18 @@ internal static async Task<bool> TryLoadGameDetails(PresetConfig config = null)

_gameHomepageLink = config.ZoneURL;
_gameDescription = config.ZoneDescription;

_gamePosterPath = config.GameType switch
{
GameNameType.Honkai => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_honkai.png"),
GameNameType.Genshin => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_genshin.png"),
GameNameType.StarRail => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_starrail.png"),
GameNameType.Zenless => Path.Combine(AppFolder, @"Assets\Images\GamePoster\poster_zzz.png"),
_ => AppDefaultBG
};

// TODO: Use FallbackCDNUtil to get the sprites
_gamePosterPath = await ImageLoaderHelper.GetCachedSpritesAsync(FallbackCDNUtil.TryGetAbsoluteToRelativeCDNURL(config.ZonePosterURL, "metadata/"), default);
//_gamePosterPath = await ImageLoaderHelper.GetCachedSpritesAsync(FallbackCDNUtil.TryGetAbsoluteToRelativeCDNURL(config.ZonePosterURL, "metadata/"), default);
_gameLogoPath = await ImageLoaderHelper.GetCachedSpritesAsync(FallbackCDNUtil.TryGetAbsoluteToRelativeCDNURL(config.ZoneLogoURL, "metadata/"), default);

using (IRandomAccessStream fs2 = new FileStream(_gameLogoPath, FileMode.Open, FileAccess.Read, FileShare.Read).AsRandomAccessStream())
Expand Down

0 comments on commit 7ef4fab

Please sign in to comment.