Skip to content

Commit

Permalink
Preview 1.81.4 Release (#565)
Browse files Browse the repository at this point in the history
# What's New? - 1.81.4
- **[Fix]** Inability to download preload for Genshin Impact due to
wrong variable assignment, by @Cryotechnic
- **[New]** Regional Custom Background, by @Cryotechnic, @neon-nyan, &
@bagusnl
- You can now set a custom background of your choice per game region.
You can access the settings in the Home Page -> Quick Settings (bottom
right) -> Custom Background for Region.
- This feature does not require you to enable the global custom
background settings. Background priority as follows: Regional Custom BG
-> Global App Custom BG -> API provided BG -> Paimon deadge fallback.
  - Yes, support video background as well.
- **[Fix]** Events button stacked with API provided background, by
@bagusnl
  - Literally just need to kick the event button 10px down...
- **[Imp]** Game Launch Commands code improvements, by @bagusnl 
- Made PostGLC as static method so for those who runs an app that keeps
running wayyyy after the game exited, this won't cause any issues
anymore when this method gets invoked again.
- Unsubscribe from the command events after they exited to free
resources.
- **[Fix]** Errors when doing Game Files Cleanup due to multi-thread
download, by @neon-nyan
- **[Fix]** Game Settings backend code adjustments, by @bagusnl 
  - Don't force save settings that is not yet loaded to prevent crashes.
- [StarRail] Don't save Graphics settings if A/B settings flag is found.
- **[Fix]** Inability to switch custom background from video to image
without launcher restart, by @neon-nyan
- Caused by the opacity for still image background handler to be set to
0 when loading video background, but never get sets back to 1 when
loading still image afterwards.
  - Cumulative man hours wasted: 6+ hours.
- **[Fix]** Prevent ACE (Anti-Cheat Expert) binaries to get removed from
File Game Cleanup, by @Cryotechnic
- **[Fix]** Event panel is not shown when "Event" news tag is empty, by
@neon-nyan

### Templates

<details>
  <summary>Changelog Prefixes</summary>
  
  ```
    **[New]**
    **[Imp]**
    **[Fix]**
    **[Loc]**
    **[Doc]**
  ```

</details>
  • Loading branch information
neon-nyan committed Aug 26, 2024
2 parents e478a29 + 0eeba95 commit 0c2ef33
Show file tree
Hide file tree
Showing 61 changed files with 1,222 additions and 680 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions CollapseLauncher.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CDNURL/@EntryIndexedValue">CDNURL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FX/@EntryIndexedValue">FX</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FXAA/@EntryIndexedValue">FXAA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GLC/@EntryIndexedValue">GLC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HD/@EntryIndexedValue">HD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HDR/@EntryIndexedValue">HDR</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
Expand Down
44 changes: 20 additions & 24 deletions CollapseLauncher/Classes/CachesManagement/StarRail/Fetch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,32 +80,28 @@ private async Task<List<SRAsset>> Fetch(CancellationToken token)
_status!.IsIncludePerFileIndicator = false;
UpdateStatus();

try
// Start reading the metadata and build the asset index of each type
SRAssetProperty assetProperty;
switch (type)
{
// Start reading the metadata and build the asset index of each type
SRAssetProperty assetProperty;
switch (type)
{
case SRAssetType.IFix:
await _innerGameVersionManager!.StarRailMetadataTool!.ReadIFixMetadataInformation(token);
assetProperty = _innerGameVersionManager!.StarRailMetadataTool!.MetadataIFix!.GetAssets();
assetIndex!.AddRange(assetProperty!.AssetList!);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
case SRAssetType.DesignData:
await _innerGameVersionManager!.StarRailMetadataTool!.ReadDesignMetadataInformation(token);
assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataDesign!.GetAssets();
assetIndex!.AddRange(assetProperty!.AssetList!);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
case SRAssetType.Lua:
await _innerGameVersionManager!.StarRailMetadataTool!.ReadLuaMetadataInformation(token);
assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataLua!.GetAssets();
assetIndex!.AddRange(assetProperty!.AssetList!);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
}

return (0, 0);
case SRAssetType.IFix:
await _innerGameVersionManager!.StarRailMetadataTool!.ReadIFixMetadataInformation(token);
assetProperty = _innerGameVersionManager!.StarRailMetadataTool!.MetadataIFix!.GetAssets();
assetIndex!.AddRange(assetProperty!.AssetList!);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
case SRAssetType.DesignData:
await _innerGameVersionManager!.StarRailMetadataTool!.ReadDesignMetadataInformation(token);
assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataDesign!.GetAssets();
assetIndex!.AddRange(assetProperty!.AssetList!);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
case SRAssetType.Lua:
await _innerGameVersionManager!.StarRailMetadataTool!.ReadLuaMetadataInformation(token);
assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataLua!.GetAssets();
assetIndex!.AddRange(assetProperty!.AssetList!);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
}
catch { throw; }

return (0, 0);
}

#region Utilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class CancellationTokenSourceWrapper : CancellationTokenSource

public new void Cancel()
{
if (!base.IsCancellationRequested) base.Cancel();
if (!IsCancellationRequested) base.Cancel();
IsCancelled = true;
}

Expand Down
3 changes: 1 addition & 2 deletions CollapseLauncher/Classes/Extension/TaskExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ internal static class TaskExtensions
catch (Exception ex)
{
lastException = ex;
actionOnRetry?.Invoke(retryAttemptCurrent, retryAttempt ?? 0, timeout ?? 0, timeoutStep ?? 0);
actionOnRetry?.Invoke(retryAttemptCurrent, (int)retryAttempt, timeout ?? 0, timeoutStep ?? 0);

if (ex is TimeoutException)
{
Expand All @@ -60,7 +60,6 @@ internal static class TaskExtensions

retryAttemptCurrent++;
timeout += timeoutStep;
continue;
}
finally
{
Expand Down
41 changes: 23 additions & 18 deletions CollapseLauncher/Classes/Extension/UIElementExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,11 @@ internal static void AddGridColumns(this Grid grid, params GridLength[] columnWi
if (columnWidths.Length == 0)
throw new IndexOutOfRangeException($"\"columnWidth\" cannot be empty!");

for (int i = 0; i < columnWidths.Length; i++) grid.ColumnDefinitions.Add(new ColumnDefinition()
{
Width = columnWidths[i]
});
for (int i = 0; i < columnWidths.Length; i++)
grid.ColumnDefinitions.Add(new ColumnDefinition()
{
Width = columnWidths[i]
});
}

internal static void AddGridColumns(this Grid grid, int count, GridLength? columnWidth = null)
Expand Down Expand Up @@ -221,11 +222,15 @@ internal static CornerRadius GetElementCornerRadius(FrameworkElement element, Co
internal static CornerRadius AttachRoundedKindCornerRadius(FrameworkElement element)
{
CornerRadius initialRadius = GetElementCornerRadius(element, CornerRadiusKind.Rounded);
element.SizeChanged += (sender, _) => InnerSetCornerRadius(element, GetElementCornerRadius(element, CornerRadiusKind.Rounded));
element.SizeChanged += (_, _) => InnerSetCornerRadius(element, GetElementCornerRadius(element, CornerRadiusKind.Rounded));
return initialRadius;
}

internal static void FindAndSetTextBlockWrapping(this UIElement element, TextWrapping wrap = TextWrapping.Wrap, HorizontalAlignment posAlign = HorizontalAlignment.Center, TextAlignment textAlign = TextAlignment.Center, bool recursiveAssignment = false, bool isParentAButton = false)
internal static void FindAndSetTextBlockWrapping(this UIElement element,
TextWrapping wrap = TextWrapping.Wrap,
HorizontalAlignment posAlign = HorizontalAlignment.Center,
TextAlignment textAlign = TextAlignment.Center,
bool recursiveAssignment = false, bool isParentAButton = false)
{
if (element is not null && element is TextBlock textBlock)
{
Expand All @@ -242,28 +247,28 @@ internal static void FindAndSetTextBlockWrapping(this UIElement element, TextWra
if (element is ButtonBase button)
{
if (button.Content is UIElement buttonContent)
buttonContent.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, recursiveAssignment, true);
buttonContent.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, true, true);
else if (button.Content is string buttonString)
button.Content = new TextBlock { Text = buttonString, TextWrapping = wrap, HorizontalAlignment = HorizontalAlignment.Center };
}

if (element is Panel panel)
foreach (UIElement childrenElement in panel.Children!)
childrenElement.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, recursiveAssignment, isParentAButton);
childrenElement.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, true, isParentAButton);

if (element is ScrollViewer scrollViewer && scrollViewer.Content is UIElement elementInner)
elementInner.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, recursiveAssignment, isParentAButton);
elementInner.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, true, isParentAButton);

if (element is ContentControl contentControl && (element is SettingsCard || element is Expander) && contentControl.Content is UIElement contentControlInner)
{
contentControlInner.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, recursiveAssignment, isParentAButton);
contentControlInner.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, true, isParentAButton);

if (contentControl is Expander expander && expander.Header is UIElement expanderHeader)
expanderHeader.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, recursiveAssignment, isParentAButton);
expanderHeader.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, true, isParentAButton);
}

if (element is InfoBar infoBar && infoBar.Content is UIElement infoBarInner)
infoBarInner.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, recursiveAssignment, isParentAButton);
infoBarInner.FindAndSetTextBlockWrapping(wrap, posAlign, textAlign, true, isParentAButton);
}

internal static ref TElement WithWidthAndHeight<TElement>(this TElement element, double uniform)
Expand Down Expand Up @@ -657,9 +662,7 @@ private static void InnerSetCornerRadius<TElement>(TElement element, CornerRadiu
internal static void ApplyDropShadow(this FrameworkElement element, Color? shadowColor = null,
double blurRadius = 10, double opacity = 0.25, bool isMasked = true, Vector3? offset = null)
{
FrameworkElement shadowPanel = null;

shadowPanel = element.FindDescendant("ShadowGrid");
var shadowPanel = element.FindDescendant("ShadowGrid");
if (shadowPanel == null)
{
shadowPanel = CreateGrid()
Expand Down Expand Up @@ -698,7 +701,7 @@ void AssignShadowAttachment(FrameworkElement thisElement, bool innerMasked)
}
}

void AttachShadow(FrameworkElement thisElement, bool innerMask, Vector3? offset)
void AttachShadow(FrameworkElement thisElement, bool innerMask, Vector3? _offset)
{
FrameworkElement xamlRoot = (thisElement.Parent as FrameworkElement) ?? thisElement.FindDescendant<Grid>();

Expand All @@ -717,7 +720,7 @@ void AttachShadow(FrameworkElement thisElement, bool innerMask, Vector3? offset)
if (xamlRoot == null || xamlRoot is not Panel)
throw new NullReferenceException("The element must be inside of a Grid or StackPanel or any \"Panel\" elements");

thisElement.ApplyDropShadow(shadowPanel, shadowColor, blurRadius, opacity, innerMask, offset);
thisElement.ApplyDropShadow(shadowPanel, shadowColor, blurRadius, opacity, innerMask, _offset);
}
catch (Exception ex)
{
Expand All @@ -731,7 +734,9 @@ internal static void ApplyDropShadow(this FrameworkElement from, FrameworkElemen
double blurRadius = 10, double opacity = 0.25, bool isMasked = false, Vector3? offset = null)
{
offset ??= Vector3.Zero;
string passedValue = $"{offset?.X ?? 0},{offset?.Y ?? 0},{offset?.Z ?? 0}";
// ReSharper disable ConstantConditionalAccessQualifier
string passedValue = $"{offset?.X},{offset?.Y},{offset?.Z}";
// ReSharper restore ConstantConditionalAccessQualifier

AttachedDropShadow shadow = new AttachedDropShadow()
{
Expand Down
85 changes: 43 additions & 42 deletions CollapseLauncher/Classes/FileMigrationProcess/IO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,52 +23,52 @@ private async Task MoveWriteFile(FileMigrationProcessUIRef uiRef, FileInfo input
byte[] buffer = new byte[bufferSize];

await using (FileStream inputStream = inputFile.OpenRead())
await using (FileStream outputStream = outputFile!.Exists && outputFile.Length <= inputFile.Length ?
outputFile.Open(FileMode.Open) : outputFile.Create())
{
// Set the output file size to inputStream's if the length is more than inputStream
if (outputStream.Length > inputStream.Length)
outputStream.SetLength(inputStream.Length);

// Just in-case if the previous move is incomplete, then update and seek to the last position.
if (outputStream.Length <= inputStream.Length && outputStream.Length >= bufferSize)
await using (FileStream outputStream = outputFile!.Exists && outputFile.Length <= inputFile.Length ?
outputFile.Open(FileMode.Open) : outputFile.Create())
{
// Do check by comparing the first and last 128K data of the file
Memory<byte> firstCompareInputBytes = new byte[bufferSize];
Memory<byte> firstCompareOutputBytes = new byte[bufferSize];
Memory<byte> lastCompareInputBytes = new byte[bufferSize];
Memory<byte> lastCompareOutputBytes = new byte[bufferSize];

// Seek to the first data
inputStream.Position = 0;
await inputStream.ReadExactlyAsync(firstCompareInputBytes);
outputStream.Position = 0;
await outputStream.ReadExactlyAsync(firstCompareOutputBytes);

// Seek to the last data
long lastPos = outputStream.Length - bufferSize;
inputStream.Position = lastPos;
await inputStream.ReadExactlyAsync(lastCompareInputBytes);
outputStream.Position = lastPos;
await outputStream.ReadExactlyAsync(lastCompareOutputBytes);

bool isMatch = firstCompareInputBytes.Span.SequenceEqual(firstCompareOutputBytes.Span)
&& lastCompareInputBytes.Span.SequenceEqual(lastCompareOutputBytes.Span);

// If the buffers don't match, then start the copy from the beginning
if (!isMatch)
// Set the output file size to inputStream's if the length is more than inputStream
if (outputStream.Length > inputStream.Length)
outputStream.SetLength(inputStream.Length);

// Just in-case if the previous move is incomplete, then update and seek to the last position.
if (outputStream.Length <= inputStream.Length && outputStream.Length >= bufferSize)
{
// Do check by comparing the first and last 128K data of the file
Memory<byte> firstCompareInputBytes = new byte[bufferSize];
Memory<byte> firstCompareOutputBytes = new byte[bufferSize];
Memory<byte> lastCompareInputBytes = new byte[bufferSize];
Memory<byte> lastCompareOutputBytes = new byte[bufferSize];

// Seek to the first data
inputStream.Position = 0;
await inputStream.ReadExactlyAsync(firstCompareInputBytes);
outputStream.Position = 0;
await outputStream.ReadExactlyAsync(firstCompareOutputBytes);

// Seek to the last data
long lastPos = outputStream.Length - bufferSize;
inputStream.Position = lastPos;
await inputStream.ReadExactlyAsync(lastCompareInputBytes);
outputStream.Position = lastPos;
await outputStream.ReadExactlyAsync(lastCompareOutputBytes);

bool isMatch = firstCompareInputBytes.Span.SequenceEqual(firstCompareOutputBytes.Span)
&& lastCompareInputBytes.Span.SequenceEqual(lastCompareOutputBytes.Span);

// If the buffers don't match, then start the copy from the beginning
if (!isMatch)
{
inputStream.Position = 0;
outputStream.Position = 0;
}
else
{
UpdateSizeProcessed(uiRef, outputStream.Length);
}
}
else
{
UpdateSizeProcessed(uiRef, outputStream.Length);
}
}

await MoveWriteFileInner(uiRef, inputStream, outputStream, buffer, token);
}
await MoveWriteFileInner(uiRef, inputStream, outputStream, buffer, token);
}

inputFile.IsReadOnly = false;
inputFile.Delete();
Expand Down Expand Up @@ -109,8 +109,9 @@ private async ValueTask<bool> IsOutputPathSpaceSufficient(string _inputPath, str
});
return returnSize;
});

if (IsSameOutputDrive = (inputDriveInfo.Name == outputDriveInfo.Name))

IsSameOutputDrive = inputDriveInfo.Name == outputDriveInfo.Name;
if (IsSameOutputDrive)
return true;

bool isSpaceSufficient = outputDriveInfo.TotalFreeSpace > TotalFileSize;
Expand Down
Loading

0 comments on commit 0c2ef33

Please sign in to comment.