Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
41500b5
[Plugin] Implement preload download and safe callbacks
Cryotechnic Mar 18, 2026
f5995e9
Bump ILLink.Tasks to 10.0.5; add .NET ref packs
Cryotechnic Mar 18, 2026
6a71b12
Add per-file progress callback support
Cryotechnic Mar 18, 2026
b62a37e
Make TryRegisterPerFileProgressCallback unsafe for improved performance
Cryotechnic Mar 19, 2026
6bdf973
Update FFmpeg installation note for clarity and conciseness
Cryotechnic Mar 19, 2026
f74ab60
Merge branch 'main' into feat/plugin-preload
Cryotechnic Mar 30, 2026
763ff55
Update localization references in plugin installation progress messages
Cryotechnic Mar 30, 2026
5ded46e
Prevent multiple allocations of per-file progress callback delegate
Cryotechnic Mar 30, 2026
0023f0c
Add per-file progress indicator status updates during preload
Cryotechnic Mar 30, 2026
7f2b766
Update download status handling to reflect success or failure
Cryotechnic Mar 30, 2026
085bd65
Handle OperationCanceledException in preload status check
Cryotechnic Mar 30, 2026
2d10717
Re-throw exception after logging preload failure in StartPackageDownload
Cryotechnic Mar 30, 2026
ddf66a8
Enhance file cleanup process and error handling in PluginGameInstallW…
Cryotechnic Mar 30, 2026
52d3ae7
Require scroll-to-bottom before accepting license agreement dialog
Cryotechnic Mar 31, 2026
a7a1b9b
[skip ci] Sync translation Translate en_US.json in de_DE
transifex-integration[bot] Apr 1, 2026
14d74bf
docs: update README.md [skip ci]
allcontributors[bot] Apr 1, 2026
0e8e498
docs: update .all-contributorsrc [skip ci]
allcontributors[bot] Apr 1, 2026
1dab2ad
docs: add perfectdelusions as a contributor for translation (#867)
bagusnl Apr 1, 2026
a30d984
Simplify BitmapIcon Create
neon-nyan Apr 3, 2026
cdec12d
Update MainPage.Navigation.cs
neon-nyan Apr 3, 2026
277a83c
Log error when unregistering per-file progress callback in PluginInfo
Cryotechnic Apr 4, 2026
9ad64fd
Add null check for progress in PluginGameInstallWrapper to prevent ex…
Cryotechnic Apr 4, 2026
df8717f
[skip ci] Sync translation Translate en_US.json in ja_JP
transifex-integration[bot] Apr 5, 2026
ff64a98
[skip ci] Sync translation Translate en_US.json in ja_JP
transifex-integration[bot] Apr 5, 2026
e02ab8b
Implement async preload download with per-file progress callbacks (#865)
neon-nyan Apr 5, 2026
ff1e82b
Simplify method to add navigation items
neon-nyan Apr 5, 2026
ba0472d
Update EncTool repo
neon-nyan Apr 5, 2026
c44c7f4
Update submodule
neon-nyan Apr 5, 2026
edbd6ae
Update NuGet
neon-nyan Apr 5, 2026
517ae11
Update ImageEx
neon-nyan Apr 5, 2026
55f4403
Fix ReturnToHomePage not refreshing after returning to its game
neon-nyan Apr 5, 2026
f87ef76
Fix deleted files re-downloaded on ZZZ and HSR update
neon-nyan Apr 5, 2026
bd26158
Refactor Hi3 CG metadata parser
neon-nyan Apr 5, 2026
5c0e414
Remove inclusion of postproc on FFmpeg
neon-nyan Apr 5, 2026
0875136
Revert "Remove inclusion of postproc on FFmpeg"
neon-nyan Apr 5, 2026
5ba9bd2
Improve Hi3 Cache Update and Game Repair file checks
neon-nyan Apr 6, 2026
00ce752
[skip ci] Sync translation Translate en_US.json in id_ID
transifex-integration[bot] Apr 6, 2026
ecc5919
[skip ci] Sync translation Translate en_US.json in zh_CN
transifex-integration[bot] Apr 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,15 @@
"contributions": [
"translation"
]
},
{
"login": "perfectdelusions",
"name": "eden",
"avatar_url": "https://avatars.githubusercontent.com/u/272893080?v=4",
"profile": "https://github.com/perfectdelusions",
"contributions": [
"translation"
]
}
],
"repoType": "github"
Expand Down
23 changes: 13 additions & 10 deletions CollapseLauncher/Classes/CachesManagement/Honkai/Check.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,6 @@ private async Task<List<CacheAsset>> Check(List<CacheAsset> assetIndex, Cancella
return returnAsset;
}

private readonly SearchValues<string> _unusedSearchValues = SearchValues.Create([
"output_log",
"Crashes",
"Verify.txt",
"APM",
"FBData",
"asb.dat"
], StringComparison.OrdinalIgnoreCase);

private void CheckUnusedAssets(List<CacheAsset> assetIndex, List<CacheAsset> returnAsset)
{
// Directory info and if the directory doesn't exist, return
Expand All @@ -76,13 +67,25 @@ private void CheckUnusedAssets(List<CacheAsset> assetIndex, List<CacheAsset> ret
return;
}

SearchValues<string> unusedSearchValues = SearchValues
.Create(GameVersionManager.GamePreset.GameInstallFileInfo?.CacheUpdateUnusedFilesIgnoreList
?? [
"output_log",
"Crashes",
"Verify.txt",
"APM",
"FBData",
"asb.dat",
"MiHoYoSDK.log"
], StringComparison.OrdinalIgnoreCase);

// Iterate the file contained in the _gamePath
foreach (FileInfo fileInfo in directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories)
.EnumerateNoReadOnly())
{
ReadOnlySpan<char> filePath = fileInfo.FullName;

if (filePath.ContainsAny(_unusedSearchValues)
if (filePath.ContainsAny(unusedSearchValues)
|| assetIndex.Exists(x => x.ConcatPath == fileInfo.FullName))
{
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
using CollapseLauncher.Plugins;
using Hi3Helper;
using Hi3Helper.Data;
using Hi3Helper.Shared.Region;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;

// ReSharper disable StringLiteralTypo
Expand Down Expand Up @@ -67,23 +69,24 @@ private static IconElement GetGamePresetIcon(PresetConfig presetConfig)

if (presetConfig is not PluginPresetConfigWrapper pluginPresetConfig)
{
return new BitmapIcon
{
UriSource = new Uri(uri)
};
return Create(uri);
}

PluginInfo pluginInfo = pluginPresetConfig.PluginInfo;
GamePluginIconConverter converter = StaticConverter<GamePluginIconConverter>.Shared;
if (converter.Convert(pluginInfo, null!, null!, "") is not IconElement iconElement)
{
return new BitmapIcon
{
UriSource = new Uri(uri)
};
return Create(uri);
}

return iconElement;

static BitmapIcon Create(string uri)
=> new()
{
UriSource = new Uri(uri),
ShowAsMonochrome = false
};
}

private static void AttachEventToNotification(PresetConfig presetConfig, IBackgroundActivity activity, string activityTitle, string activitySubtitle)
Expand Down
11 changes: 6 additions & 5 deletions CollapseLauncher/Classes/Helper/Metadata/PresetConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ public enum LauncherType

public class GameInstallFileInfo
{
public string GameDataFolderName { get; init; } = string.Empty;
public string[] FilesToDelete { get; init; } = [];
public string[] FoldersToDelete { get; init; } = [];
public string[] FoldersToKeepInData { get; init; } = [];
public string[] FilesCleanupIgnoreList { get; init; } = [];
public string GameDataFolderName { get; init; } = string.Empty;
public string[] FilesToDelete { get; init; } = [];
public string[] FoldersToDelete { get; init; } = [];
public string[] FoldersToKeepInData { get; init; } = [];
public string[] FilesCleanupIgnoreList { get; init; } = [];
public string[] CacheUpdateUnusedFilesIgnoreList { get; init; } = [];
}

public class SophonChunkUrls
Expand Down
32 changes: 23 additions & 9 deletions CollapseLauncher/Classes/Helper/StreamUtility/StreamExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,28 +309,42 @@ public static FileInfo ResolveSymlink(this FileInfo fileInfo)
/// </summary>
/// <param name="dir">The directory to remove.</param>
/// <param name="recursive">Whether to remove all possibly empty directories recursively.</param>
public static void DeleteEmptyDirectory(this string dir, bool recursive = false)
public static bool DeleteEmptyDirectory(this string dir, bool recursive = false)
=> new DirectoryInfo(dir).DeleteEmptyDirectory(recursive);

/// <summary>
/// Deletes the directory if it is empty.
/// </summary>
/// <param name="dir">The directory to remove.</param>
/// <param name="recursive">Whether to remove all possibly empty directories recursively.</param>
public static void DeleteEmptyDirectory(this DirectoryInfo dir, bool recursive = false)
public static bool DeleteEmptyDirectory(this DirectoryInfo dir, bool recursive = false)
{
if (recursive)
try
{
foreach (DirectoryInfo childDir in dir.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
if (!dir.Exists)
{
childDir.DeleteEmptyDirectory();
return true;
}

if (recursive)
{
foreach (DirectoryInfo childDir in dir.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
{
childDir.DeleteEmptyDirectory();
}
}
}

FindFiles.TryIsDirectoryEmpty(dir.FullName, out bool isEmpty);
if (isEmpty)
FindFiles.TryIsDirectoryEmpty(dir.FullName, out bool isEmpty);
if (isEmpty)
{
dir.Delete(true);
}

return true;
}
catch
{
dir.Delete(true);
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ await TryGetAdditionalPackageForSophonDiff(httpClient,
}

// Filter asset list
await FilterSophonPatchAssetList(sophonUpdateAssetList, Token!.Token);
await FilterAssetList(sophonUpdateAssetList, x => x.AssetName, Token!.Token);

// Get the remote chunk size
ProgressPerFileSizeTotal = sophonUpdateAssetList.GetCalculatedDiffSize(!isPreloadMode);
Expand Down Expand Up @@ -925,12 +925,6 @@ await Parallel.ForEachAsync(sophonUpdateAssetList
}
}

protected virtual Task FilterSophonPatchAssetList(List<SophonAsset> itemList, CancellationToken token)
{
// NOP
return Task.CompletedTask;
}

private ValueTask RunSophonAssetDownloadThread(HttpClient client,
SophonAsset asset,
ParallelOptions parallelOptions)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Hi3Helper.Data;
using Hi3Helper;
using Hi3Helper.Data;
using System;
using System.Buffers;
using System.Collections.Generic;
Expand Down Expand Up @@ -62,9 +63,13 @@ public override async Task FilterAssetList<T>(
continue;
}

ConverterTool.NormalizePathInplaceNoTrim(filePath);

int indexOfAny = filePath.IndexOfAny(searchValues);
if (indexOfAny >= 0)
{
Logger.LogWriteLine($"[StarRailInstall::FilterAssetList] Asset: {patchAsset} is ignored due to marked as deleted asset.",
writeToLog: true);
continue;
}

Expand All @@ -90,12 +95,9 @@ static ReadOnlySpan<char> GetFilePathFromJson(ReadOnlySpan<char> line)
line = line[(firstIndexOf + first.Length)..];
int endIndexOf = line.IndexOf(end);

if (endIndexOf <= 0)
{
return ReadOnlySpan<char>.Empty;
}

return line[..endIndexOf];
return endIndexOf <= 0
? ReadOnlySpan<char>.Empty
: line[..endIndexOf];
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
using Hi3Helper.Sophon;
using Hi3Helper.Sophon.Infos;
using Hi3Helper;
using Hi3Helper.Sophon.Structs;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
// ReSharper disable CheckNamespace
Expand All @@ -17,14 +15,6 @@ internal partial class ZenlessInstall
{
private const StringSplitOptions SplitOptions = StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries;

// ReSharper disable once StringLiteralTypo
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<SophonChunksInfo>k__BackingField")]
private static extern ref SophonChunksInfo GetChunkAssetChunksInfo(SophonAsset element);

// ReSharper disable once StringLiteralTypo
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<SophonChunksInfoAlt>k__BackingField")]
private static extern ref SophonChunksInfo GetChunkAssetChunksInfoAlt(SophonAsset element);

public override async Task FilterAssetList<T>(
List<T> itemList,
Func<T, string?> itemPathSelector,
Expand Down Expand Up @@ -67,6 +57,8 @@ private static void FilterSophonAsset<T>(List<T> itemList, HashSet<string> excep
if (asset is SophonIdentifiableProperty { MatchingField: { } assetMatchingField } &&
exceptMatchFieldHashSet.Contains(assetMatchingField))
{
Logger.LogWriteLine($"[ZenlessInstall::FilterSophonAsset] Asset: {asset} is ignored due to marked as deleted asset.",
writeToLog: true);
continue;
}

Expand Down
Loading