Skip to content

Commit 66b9c3e

Browse files
authored
Preview 1.82.19 Hotfix Release (#698)
# What's changed? - 1.82.19 - **[Fix]** Carousel keep running in background, by @neon-nyan - **[Fix]** [ZZZ GSP] Windowed resolution is in wrong order, by @neon-nyan - **[Fix]** Crash when spawning background activity notification, by @neon-nyan - **[Fix]** [SR Repair] Prevent hash file marked as unused, by @neon-nyan - **[Fix]** Notification not bring up window after click, by @neon-nyan - **[New]** [SR GSP] Deprecate Mobile mode feature, by @bagusnl - Due to the last game changes causing the feature to not work anymore and fixing it requires memory injection which we do not do (see contribution guidelines) - Users can still toggle the settings, but warning is in place - **[Fix]** Notification toast does not bring up the main window, by @neon-nyan - Thanks Microsoft, for another undocumented thing you need to do to have a Windows app working! - **[Loc]** Sync localization, thanks localizers <3 - Massive sync up for ko-KR locale, thanks Youras65, DY3413, @despenser08 (sorry if I missed any one) - **[Doc]** Updated legal documentations to match up the year, by @bagusnl ![march7tpn](https://github.com/user-attachments/assets/42c8befb-bbab-46c9-852b-06626e341f48) <details> <summary>Changelog Prefixes</summary> ``` **[New]** **[Imp]** **[Fix]** **[Loc]** **[Doc]** ``` </details>
2 parents 5b5c2ed + 6b55512 commit 66b9c3e

File tree

68 files changed

+1827
-920
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1827
-920
lines changed

.github/workflows/qodana-scan-pr.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ on:
33
pull_request:
44
branches:
55
- main
6+
- '*staging'
67
paths-ignore:
78
- '**.md'
89
- 'Hi3Helper.Core/Lang/**.json'
@@ -51,7 +52,7 @@ jobs:
5152

5253
- name: 'Qodana Scan'
5354
if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }}
54-
uses: JetBrains/qodana-action@latest
55+
uses: JetBrains/qodana-action@next
5556
with:
5657
args: --ide,QDNET
5758
pr-mode: true

CollapseLauncher.sln

+8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "H.GeneratedIcons.System.Dra
3838
EndProject
3939
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hi3Helper.Win32", "Hi3Helper.Win32\Hi3Helper.Win32.csproj", "{F65C6DAC-CC04-214B-9430-2C4AE31448E2}"
4040
EndProject
41+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hi3Helper.Win32.WinRT", "Hi3Helper.Win32\WinRT\Hi3Helper.Win32.WinRT.csproj", "{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}"
42+
EndProject
4143
Global
4244
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4345
Debug|x64 = Debug|x64
@@ -152,6 +154,12 @@ Global
152154
{F65C6DAC-CC04-214B-9430-2C4AE31448E2}.Publish|x64.Build.0 = Release|x64
153155
{F65C6DAC-CC04-214B-9430-2C4AE31448E2}.Release|x64.ActiveCfg = Release|x64
154156
{F65C6DAC-CC04-214B-9430-2C4AE31448E2}.Release|x64.Build.0 = Release|x64
157+
{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}.Debug|x64.ActiveCfg = Debug|x64
158+
{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}.Debug|x64.Build.0 = Debug|x64
159+
{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}.Publish|x64.ActiveCfg = Release|x64
160+
{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}.Publish|x64.Build.0 = Release|x64
161+
{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}.Release|x64.ActiveCfg = Release|x64
162+
{5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD}.Release|x64.Build.0 = Release|x64
155163
EndGlobalSection
156164
GlobalSection(SolutionProperties) = preSolution
157165
HideSolutionNode = FALSE

CollapseLauncher.slnx

+4
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,8 @@
7878
<BuildType Solution="Publish|*" Project="Release" />
7979
<Platform Project="x64" />
8080
</Project>
81+
<Project Path="Hi3Helper.Win32\WinRT\Hi3Helper.Win32.WinRT.csproj" Id="5CA5A261-1D5B-8A4D-EA87-B031CFFD4DDD">
82+
<BuildType Solution="Publish|*" Project="Release" />
83+
<Platform Project="x64" />
84+
</Project>
8185
</Solution>
Loading

CollapseLauncher/Classes/EventsManagement/BackgroundActivityManager.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CollapseLauncher.Dialogs;
22
using CollapseLauncher.Extension;
3+
using CollapseLauncher.Helper;
34
using CollapseLauncher.Helper.Metadata;
45
using CollapseLauncher.Interfaces;
56
using CollapseLauncher.Statics;
@@ -29,7 +30,8 @@ public static void Attach(int hashID, IBackgroundActivity activity, string activ
2930
return;
3031
}
3132

32-
AttachEventToNotification(hashID, activity, activityTitle, activitySubtitle);
33+
WindowUtility.CurrentDispatcherQueue?
34+
.TryEnqueue(() => AttachEventToNotification(hashID, activity, activityTitle, activitySubtitle));
3335
BackgroundActivities.Add(hashID, activity);
3436
#if DEBUG
3537
Logger.LogWriteLine($"Background activity with ID: {hashID} has been attached", LogType.Debug, true);
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
using System;
2-
using System.Runtime.CompilerServices;
1+
using System.Runtime.CompilerServices;
32
using System.Threading;
43
using System.Threading.Tasks;
54
// ReSharper disable UnusedMember.Global
5+
// ReSharper disable CheckNamespace
66

77
#nullable enable
88
namespace CollapseLauncher.Extension
@@ -11,35 +11,13 @@ namespace CollapseLauncher.Extension
1111

1212
internal static partial class TaskExtensions
1313
{
14-
internal static Task<TResult?>
14+
internal static async Task<TResult?>
1515
WaitForRetryAsync<TResult>(this ActionTimeoutTaskAwaitableCallback<TResult?> funcCallback,
1616
int? timeout = null,
1717
int? timeoutStep = null,
1818
int? retryAttempt = null,
1919
ActionOnTimeOutRetry? actionOnRetry = null,
2020
CancellationToken fromToken = default)
21-
=> WaitForRetryAsync(() => funcCallback, timeout, timeoutStep, retryAttempt, actionOnRetry, fromToken);
22-
23-
internal static async Task<TResult?>
24-
WaitForRetryAsync<TResult>(Func<ActionTimeoutTaskAwaitableCallback<TResult?>> funcCallback,
25-
int? timeout = null,
26-
int? timeoutStep = null,
27-
int? retryAttempt = null,
28-
ActionOnTimeOutRetry? actionOnRetry = null,
29-
CancellationToken fromToken = default)
30-
=> await WaitForRetryAsync(funcCallback.AsTaskCallback,
31-
timeout,
32-
timeoutStep,
33-
retryAttempt,
34-
actionOnRetry,
35-
fromToken);
36-
37-
private static ActionTimeoutTaskCallback<TResult?> AsTaskCallback<TResult>(this Func<ActionTimeoutTaskAwaitableCallback<TResult?>> func) =>
38-
async ctx =>
39-
{
40-
ActionTimeoutTaskAwaitableCallback<TResult?> callback = func.Invoke();
41-
ConfiguredTaskAwaitable<TResult?> callbackAwaitable = callback.Invoke(ctx);
42-
return await callbackAwaitable;
43-
};
21+
=> await funcCallback.Invoke(fromToken);
4422
}
4523
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
using CollapseLauncher.Helper;
2+
using CollapseLauncher.Helper.Update;
3+
using Hi3Helper;
4+
using Hi3Helper.Data;
5+
using Hi3Helper.SentryHelper;
6+
using Hi3Helper.Shared.Region;
7+
using Hi3Helper.Win32.ShellLinkCOM;
8+
using Microsoft.Extensions.Logging;
9+
using NuGet.Versioning;
10+
using System;
11+
using System.IO;
12+
using System.Linq;
13+
using System.Runtime.CompilerServices;
14+
using System.Threading.Tasks;
15+
using Velopack;
16+
using Velopack.Locators;
17+
// ReSharper disable IdentifierTypo
18+
// ReSharper disable StringLiteralTypo
19+
// ReSharper disable CommentTypo
20+
21+
#nullable enable
22+
namespace CollapseLauncher.Classes.Extension
23+
{
24+
internal static class VelopackLocatorExtension
25+
{
26+
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<AppId>k__BackingField")]
27+
internal static extern ref string? GetLocatorAumidField(this WindowsVelopackLocator locator);
28+
29+
internal static void StartUpdaterHook(string aumid)
30+
{
31+
#if !USEVELOPACK
32+
// Add Squirrel Hooks
33+
SquirrelAwareApp.HandleEvents(
34+
// Add shortcut and uninstaller entry on first start-up
35+
// ReSharper disable UnusedParameter.Local
36+
(_, sqr) =>
37+
{
38+
Console
39+
.WriteLine("Please do not close this console window while Collapse is preparing the installation via Squirrel...");
40+
},
41+
(_, sqr) =>
42+
{
43+
Console
44+
.WriteLine("Please do not close this console window while Collapse is updating via Squirrel...");
45+
},
46+
onAppUninstall: (_, sqr) =>
47+
{
48+
Console
49+
.WriteLine("Uninstalling Collapse via Squirrel...\r\n" +
50+
"Please do not close this console window while action is being performed!");
51+
},
52+
// ReSharper restore UnusedParameter.Local
53+
onEveryRun: (_, _, _) => { }
54+
);
55+
#else
56+
// Allocate the Velopack locator manually to avoid Velopack from re-assigning
57+
// its custom AUMID
58+
ILogger logger = ILoggerHelper.GetILogger("Velopack");
59+
WindowsVelopackLocator locator = new WindowsVelopackLocator(logger);
60+
// HACK: Always ensure to set the AUMID field null so it won't
61+
// set the AUMID to its own.
62+
locator.GetLocatorAumidField() = null;
63+
64+
VelopackApp builder = VelopackApp.Build()
65+
.WithRestarted(TryCleanupFallbackUpdate)
66+
.WithAfterUpdateFastCallback(TryCleanupFallbackUpdate)
67+
.WithFirstRun(TryCleanupFallbackUpdate)
68+
.SetLocator(locator);
69+
70+
builder.Run(logger);
71+
72+
_ = Task.Run(DeleteVelopackLock);
73+
74+
GenerateVelopackMetadata(aumid);
75+
76+
void DeleteVelopackLock()
77+
{
78+
// Get the current application directory
79+
string currentAppDir = AppDomain.CurrentDomain.BaseDirectory;
80+
81+
// Construct the path to the .velopack_lock file
82+
string velopackLockPath = Path.Combine(currentAppDir, "..", "packages", ".velopack_lock");
83+
84+
// Normalize the path
85+
velopackLockPath = Path.GetFullPath(velopackLockPath);
86+
87+
// Check if the file exists
88+
if (!File.Exists(velopackLockPath))
89+
{
90+
return;
91+
}
92+
93+
// Delete the file
94+
File.Delete(velopackLockPath);
95+
Logger.LogWriteLine(".velopack_lock file deleted successfully.");
96+
}
97+
#endif
98+
}
99+
100+
#if USEVELOPACK
101+
public static void TryCleanupFallbackUpdate(SemanticVersion newVersion)
102+
{
103+
string currentExecutedAppFolder = LauncherConfig.AppExecutableDir.TrimEnd('\\');
104+
string currentExecutedPath = LauncherConfig.AppExecutablePath;
105+
106+
// If the path is not actually running under "current" velopack folder, then return
107+
#if !DEBUG
108+
if (!currentExecutedAppFolder.EndsWith("current", StringComparison.OrdinalIgnoreCase)) // Expecting "current"
109+
{
110+
Logger.LogWriteLine("[TryCleanupFallbackUpdate] The launcher does not run from \"current\" folder");
111+
return;
112+
}
113+
#endif
114+
115+
try
116+
{
117+
// Otherwise, start cleaning-up process
118+
string? currentExecutedParentFolder = Path.GetDirectoryName(currentExecutedAppFolder);
119+
if (currentExecutedParentFolder != null)
120+
{
121+
DirectoryInfo directoryInfo = new DirectoryInfo(currentExecutedParentFolder);
122+
foreach (DirectoryInfo childLegacyAppSemVerFolder in
123+
directoryInfo.EnumerateDirectories("app-*", SearchOption.TopDirectoryOnly))
124+
{
125+
// Removing the "app-*" folder
126+
childLegacyAppSemVerFolder.Delete(true);
127+
Logger.LogWriteLine($"[TryCleanupFallbackUpdate] Removed {childLegacyAppSemVerFolder.FullName} folder!",
128+
LogType.Default, true);
129+
}
130+
131+
// Try to remove squirrel temp clowd folder
132+
string squirrelTempPackagesFolder = Path.Combine(currentExecutedParentFolder, "SquirrelClowdTemp");
133+
DirectoryInfo squirrelTempPackagesFolderInfo = new DirectoryInfo(squirrelTempPackagesFolder);
134+
if (squirrelTempPackagesFolderInfo.Exists)
135+
{
136+
squirrelTempPackagesFolderInfo.Delete(true);
137+
Logger.LogWriteLine($"[TryCleanupFallbackUpdate] Removed package temp folder: {squirrelTempPackagesFolder}!",
138+
LogType.Default, true);
139+
}
140+
141+
// Try to remove stub executable
142+
string squirrelLegacyStubPath = Path.Combine(currentExecutedParentFolder, "CollapseLauncher.exe");
143+
RemoveSquirrelFilePath(squirrelLegacyStubPath);
144+
145+
// Try to remove createdump executable
146+
string squirrelLegacyDumpPath = Path.Combine(currentExecutedParentFolder, "createdump.exe");
147+
RemoveSquirrelFilePath(squirrelLegacyDumpPath);
148+
149+
// Try to remove RestartAgent executable
150+
string squirrelLegacyRestartAgentPath =
151+
Path.Combine(currentExecutedParentFolder, "RestartAgent.exe");
152+
RemoveSquirrelFilePath(squirrelLegacyRestartAgentPath);
153+
}
154+
155+
// Try to remove legacy shortcuts
156+
string? currentWindowsPathDrive = Path.GetPathRoot(Environment.SystemDirectory);
157+
if (!string.IsNullOrEmpty(currentWindowsPathDrive))
158+
{
159+
string squirrelLegacyStartMenuGlobal =
160+
Path.Combine(currentWindowsPathDrive,
161+
@"ProgramData\Microsoft\Windows\Start Menu\Programs\Collapse\Collapse Launcher");
162+
string? squirrelLegacyStartMenuGlobalParent = Path.GetDirectoryName(squirrelLegacyStartMenuGlobal);
163+
if (Directory.Exists(squirrelLegacyStartMenuGlobalParent) &&
164+
Directory.Exists(squirrelLegacyStartMenuGlobal))
165+
{
166+
Directory.Delete(squirrelLegacyStartMenuGlobalParent, true);
167+
}
168+
}
169+
170+
// Try to delete all possible shortcuts on any users (since the shortcut used will be the global one)
171+
// Only do this if shortcut path is not same as current path tho... It pain to re-pin the shortcut again...
172+
string currentUsersDirPath = Path.Combine(currentWindowsPathDrive!, "Users");
173+
foreach (string userDirInfoPath in Directory
174+
.EnumerateDirectories(currentUsersDirPath, "*",
175+
SearchOption.TopDirectoryOnly)
176+
.Where(ConverterTool.IsUserHasPermission))
177+
{
178+
// Get the shortcut file
179+
string thisUserStartMenuShortcut = Path.Combine(userDirInfoPath,
180+
@"AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Collapse.lnk");
181+
if (!File.Exists(thisUserStartMenuShortcut))
182+
{
183+
continue;
184+
}
185+
186+
// Try open the shortcut and check whether this shortcut is actually pointing to
187+
// CollapseLauncher.exe file
188+
using ShellLink shellLink = new ShellLink(thisUserStartMenuShortcut);
189+
// Try to get the target path and its filename
190+
string shortcutTargetPath = shellLink.Target;
191+
if (!shortcutTargetPath.Equals(currentExecutedPath, StringComparison.OrdinalIgnoreCase))
192+
{
193+
continue;
194+
}
195+
196+
// Compare if the filename is equal, then delete it.
197+
File.Delete(thisUserStartMenuShortcut);
198+
Logger.LogWriteLine($"[TryCleanupFallbackUpdate] Deleted old shortcut located at: " +
199+
$"{thisUserStartMenuShortcut} -> {shortcutTargetPath}",
200+
LogType.Default, true);
201+
}
202+
203+
// Try to recreate shortcuts
204+
TaskSchedulerHelper.RecreateIconShortcuts();
205+
}
206+
catch (Exception ex)
207+
{
208+
SentryHelper.ExceptionHandler(ex, SentryHelper.ExceptionType.UnhandledOther);
209+
Logger.LogWriteLine($"[TryCleanupFallbackUpdate] Failed while operating clean-up routines...\r\n{ex}");
210+
}
211+
212+
return;
213+
214+
void RemoveSquirrelFilePath(string filePath)
215+
{
216+
if (!File.Exists(filePath))
217+
{
218+
return;
219+
}
220+
221+
File.Delete(filePath);
222+
Logger.LogWriteLine($"[TryCleanupFallbackUpdate] Removed old squirrel executables: {filePath}!",
223+
LogType.Default, true);
224+
}
225+
}
226+
#endif
227+
228+
public static string FindCollapseStubPath()
229+
{
230+
var collapseMainPath = LauncherConfig.AppExecutablePath;
231+
232+
#if USEVELOPACK
233+
const string collapseExecName = "CollapseLauncher.exe";
234+
var collapseStubPath = Path.Combine(Directory.GetParent(Path.GetDirectoryName(collapseMainPath)!)!.FullName,
235+
collapseExecName);
236+
if (File.Exists(collapseStubPath))
237+
{
238+
Logger.LogWriteLine($"Found stub at {collapseStubPath}", LogType.Default, true);
239+
return collapseStubPath;
240+
}
241+
#endif
242+
243+
Logger.LogWriteLine($"Collapse stub is not used anymore, returning current executable path!\r\n\t{collapseMainPath}",
244+
LogType.Default, true);
245+
return collapseMainPath;
246+
}
247+
248+
internal static void GenerateVelopackMetadata(string aumid)
249+
{
250+
const string xmlTemplate = """
251+
<?xml version="1.0" encoding="utf-8"?>
252+
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
253+
<metadata>
254+
<id>CollapseLauncher</id>
255+
<title>Collapse</title>
256+
<description>Collapse</description>
257+
<authors>Collapse Project Team</authors>
258+
<version>{0}</version>
259+
<channel>{1}</channel>
260+
<mainExe>CollapseLauncher.exe</mainExe>
261+
<os>win</os>
262+
<rid>win</rid>
263+
<shortcutLocations>Desktop,StartMenuRoot</shortcutLocations>
264+
<shortcutAmuid>{2}</shortcutAmuid>
265+
<shortcutAumid>{2}</shortcutAumid>
266+
</metadata>
267+
</package>
268+
"""; // Adding shortcutAumid for future use, since they typo-ed the XML tag LMAO
269+
string currentVersion = LauncherUpdateHelper.LauncherCurrentVersionString;
270+
string xmlPath = Path.Combine(LauncherConfig.AppExecutableDir, "sq.version");
271+
string xmlContent = string.Format(xmlTemplate, currentVersion, LauncherConfig.IsPreview ? "preview" : "stable", aumid);
272+
File.WriteAllText(xmlPath, xmlContent.ReplaceLineEndings("\n"));
273+
Logger.LogWriteLine($"Velopack metadata has been successfully written!\r\n{xmlContent}", LogType.Default, true);
274+
}
275+
}
276+
}

0 commit comments

Comments
 (0)